Fix bug #6506 - SMBD server doesn't set EAs when a file is overwritten in NT_TRANSACT...
[Samba/gbeck.git] / source3 / utils / net_rpc_printer.c
blob21be2f43cef4c3b135e41f991cd49361cde7e0c0
1 /*
2 Samba Unix/Linux SMB client library
3 Distributed SMB/CIFS Server Management Utility
4 Copyright (C) 2004,2009 Guenther Deschner (gd@samba.org)
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #include "includes.h"
20 #include "utils/net.h"
22 /* support itanium as well */
23 static const struct print_architecture_table_node archi_table[]= {
25 {"Windows 4.0", "WIN40", 0 },
26 {"Windows NT x86", "W32X86", 2 },
27 {"Windows NT x86", "W32X86", 3 },
28 {"Windows NT R4000", "W32MIPS", 2 },
29 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
30 {"Windows NT PowerPC", "W32PPC", 2 },
31 {"Windows IA64", "IA64", 3 },
32 {"Windows x64", "x64", 3 },
33 {NULL, "", -1 }
37 /**
38 * This display-printdriver-functions was borrowed from rpcclient/cmd_spoolss.c.
39 * It is here for debugging purpose and should be removed later on.
40 **/
42 /****************************************************************************
43 Printer info level 3 display function.
44 ****************************************************************************/
46 static void display_print_driver3(struct spoolss_DriverInfo3 *r)
48 int i;
50 if (!r) {
51 return;
54 printf("Printer Driver Info 3:\n");
55 printf("\tVersion: [%x]\n", r->version);
56 printf("\tDriver Name: [%s]\n", r->driver_name);
57 printf("\tArchitecture: [%s]\n", r->architecture);
58 printf("\tDriver Path: [%s]\n", r->driver_path);
59 printf("\tDatafile: [%s]\n", r->data_file);
60 printf("\tConfigfile: [%s]\n\n", r->config_file);
61 printf("\tHelpfile: [%s]\n\n", r->help_file);
63 for (i=0; r->dependent_files[i] != NULL; i++) {
64 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
67 printf("\n");
69 printf("\tMonitorname: [%s]\n", r->monitor_name);
70 printf("\tDefaultdatatype: [%s]\n\n", r->default_datatype);
73 static void display_reg_value(const char *subkey, REGISTRY_VALUE value)
75 char *text;
77 switch(value.type) {
78 case REG_DWORD:
79 d_printf("\t[%s:%s]: REG_DWORD: 0x%08x\n", subkey, value.valuename,
80 *((uint32_t *) value.data_p));
81 break;
83 case REG_SZ:
84 rpcstr_pull_talloc(talloc_tos(),
85 &text,
86 value.data_p,
87 value.size,
88 STR_TERMINATE);
89 if (!text) {
90 break;
92 d_printf("\t[%s:%s]: REG_SZ: %s\n", subkey, value.valuename, text);
93 break;
95 case REG_BINARY:
96 d_printf("\t[%s:%s]: REG_BINARY: unknown length value not displayed\n",
97 subkey, value.valuename);
98 break;
100 case REG_MULTI_SZ: {
101 uint32_t i, num_values;
102 char **values;
104 if (!W_ERROR_IS_OK(reg_pull_multi_sz(NULL, value.data_p,
105 value.size, &num_values,
106 &values))) {
107 d_printf("reg_pull_multi_sz failed\n");
108 break;
111 for (i=0; i<num_values; i++) {
112 d_printf("%s\n", values[i]);
114 TALLOC_FREE(values);
115 break;
118 default:
119 d_printf("\t%s: unknown type %d\n", value.valuename, value.type);
125 * Copies ACLs, DOS-attributes and timestamps from one
126 * file or directory from one connected share to another connected share
128 * @param c A net_context structure
129 * @param mem_ctx A talloc-context
130 * @param cli_share_src A connected cli_state
131 * @param cli_share_dst A connected cli_state
132 * @param src_file The source file-name
133 * @param dst_file The destination file-name
134 * @param copy_acls Whether to copy acls
135 * @param copy_attrs Whether to copy DOS attributes
136 * @param copy_timestamps Whether to preserve timestamps
137 * @param is_file Whether this file is a file or a dir
139 * @return Normal NTSTATUS return.
142 NTSTATUS net_copy_fileattr(struct net_context *c,
143 TALLOC_CTX *mem_ctx,
144 struct cli_state *cli_share_src,
145 struct cli_state *cli_share_dst,
146 const char *src_name, const char *dst_name,
147 bool copy_acls, bool copy_attrs,
148 bool copy_timestamps, bool is_file)
150 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
151 int fnum_src = 0;
152 int fnum_dst = 0;
153 SEC_DESC *sd = NULL;
154 uint16_t attr;
155 time_t f_atime, f_ctime, f_mtime;
158 if (!copy_timestamps && !copy_acls && !copy_attrs)
159 return NT_STATUS_OK;
161 /* open file/dir on the originating server */
163 DEBUGADD(3,("opening %s %s on originating server\n",
164 is_file?"file":"dir", src_name));
166 fnum_src = cli_nt_create(cli_share_src, src_name, READ_CONTROL_ACCESS);
167 if (fnum_src == -1) {
168 DEBUGADD(0,("cannot open %s %s on originating server %s\n",
169 is_file?"file":"dir", src_name, cli_errstr(cli_share_src)));
170 nt_status = cli_nt_error(cli_share_src);
171 goto out;
175 if (copy_acls) {
177 /* get the security descriptor */
178 sd = cli_query_secdesc(cli_share_src, fnum_src, mem_ctx);
179 if (!sd) {
180 DEBUG(0,("failed to get security descriptor: %s\n",
181 cli_errstr(cli_share_src)));
182 nt_status = cli_nt_error(cli_share_src);
183 goto out;
186 if (c->opt_verbose && DEBUGLEVEL >= 3)
187 display_sec_desc(sd);
191 if (copy_attrs || copy_timestamps) {
193 /* get file attributes */
194 if (!cli_getattrE(cli_share_src, fnum_src, &attr, NULL,
195 &f_ctime, &f_atime, &f_mtime)) {
196 DEBUG(0,("failed to get file-attrs: %s\n",
197 cli_errstr(cli_share_src)));
198 nt_status = cli_nt_error(cli_share_src);
199 goto out;
204 /* open the file/dir on the destination server */
206 fnum_dst = cli_nt_create(cli_share_dst, dst_name, WRITE_DAC_ACCESS | WRITE_OWNER_ACCESS);
207 if (fnum_dst == -1) {
208 DEBUG(0,("failed to open %s on the destination server: %s: %s\n",
209 is_file?"file":"dir", dst_name, cli_errstr(cli_share_dst)));
210 nt_status = cli_nt_error(cli_share_dst);
211 goto out;
214 if (copy_timestamps) {
216 /* set timestamps */
217 if (!cli_setattrE(cli_share_dst, fnum_dst, f_ctime, f_atime, f_mtime)) {
218 DEBUG(0,("failed to set file-attrs (timestamps): %s\n",
219 cli_errstr(cli_share_dst)));
220 nt_status = cli_nt_error(cli_share_dst);
221 goto out;
225 if (copy_acls) {
227 /* set acls */
228 if (!cli_set_secdesc(cli_share_dst, fnum_dst, sd)) {
229 DEBUG(0,("could not set secdesc on %s: %s\n",
230 dst_name, cli_errstr(cli_share_dst)));
231 nt_status = cli_nt_error(cli_share_dst);
232 goto out;
236 if (copy_attrs) {
238 /* set attrs */
239 if (!cli_setatr(cli_share_dst, dst_name, attr, 0)) {
240 DEBUG(0,("failed to set file-attrs: %s\n",
241 cli_errstr(cli_share_dst)));
242 nt_status = cli_nt_error(cli_share_dst);
243 goto out;
248 /* closing files */
250 if (!cli_close(cli_share_src, fnum_src)) {
251 d_fprintf(stderr, "could not close %s on originating server: %s\n",
252 is_file?"file":"dir", cli_errstr(cli_share_src));
253 nt_status = cli_nt_error(cli_share_src);
254 goto out;
257 if (!cli_close(cli_share_dst, fnum_dst)) {
258 d_fprintf(stderr, "could not close %s on destination server: %s\n",
259 is_file?"file":"dir", cli_errstr(cli_share_dst));
260 nt_status = cli_nt_error(cli_share_dst);
261 goto out;
265 nt_status = NT_STATUS_OK;
267 out:
269 /* cleaning up */
270 if (fnum_src)
271 cli_close(cli_share_src, fnum_src);
273 if (fnum_dst)
274 cli_close(cli_share_dst, fnum_dst);
276 return nt_status;
280 * Copy a file or directory from a connected share to another connected share
282 * @param c A net_context structure
283 * @param mem_ctx A talloc-context
284 * @param cli_share_src A connected cli_state
285 * @param cli_share_dst A connected cli_state
286 * @param src_file The source file-name
287 * @param dst_file The destination file-name
288 * @param copy_acls Whether to copy acls
289 * @param copy_attrs Whether to copy DOS attributes
290 * @param copy_timestamps Whether to preserve timestamps
291 * @param is_file Whether this file is a file or a dir
293 * @return Normal NTSTATUS return.
296 NTSTATUS net_copy_file(struct net_context *c,
297 TALLOC_CTX *mem_ctx,
298 struct cli_state *cli_share_src,
299 struct cli_state *cli_share_dst,
300 const char *src_name, const char *dst_name,
301 bool copy_acls, bool copy_attrs,
302 bool copy_timestamps, bool is_file)
304 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
305 int fnum_src = 0;
306 int fnum_dst = 0;
307 static int io_bufsize = 64512;
308 int read_size = io_bufsize;
309 char *data = NULL;
310 off_t nread = 0;
313 if (!src_name || !dst_name)
314 goto out;
316 if (cli_share_src == NULL || cli_share_dst == NULL)
317 goto out;
319 /* open on the originating server */
320 DEBUGADD(3,("opening %s %s on originating server\n",
321 is_file ? "file":"dir", src_name));
322 if (is_file)
323 fnum_src = cli_open(cli_share_src, src_name, O_RDONLY, DENY_NONE);
324 else
325 fnum_src = cli_nt_create(cli_share_src, src_name, READ_CONTROL_ACCESS);
327 if (fnum_src == -1) {
328 DEBUGADD(0,("cannot open %s %s on originating server %s\n",
329 is_file ? "file":"dir",
330 src_name, cli_errstr(cli_share_src)));
331 nt_status = cli_nt_error(cli_share_src);
332 goto out;
336 if (is_file) {
338 /* open file on the destination server */
339 DEBUGADD(3,("opening file %s on destination server\n", dst_name));
340 fnum_dst = cli_open(cli_share_dst, dst_name,
341 O_RDWR|O_CREAT|O_TRUNC, DENY_NONE);
343 if (fnum_dst == -1) {
344 DEBUGADD(1,("cannot create file %s on destination server: %s\n",
345 dst_name, cli_errstr(cli_share_dst)));
346 nt_status = cli_nt_error(cli_share_dst);
347 goto out;
350 /* allocate memory */
351 if (!(data = (char *)SMB_MALLOC(read_size))) {
352 d_fprintf(stderr, "malloc fail for size %d\n", read_size);
353 nt_status = NT_STATUS_NO_MEMORY;
354 goto out;
360 if (c->opt_verbose) {
362 d_printf("copying [\\\\%s\\%s%s] => [\\\\%s\\%s%s] "
363 "%s ACLs and %s DOS Attributes %s\n",
364 cli_share_src->desthost, cli_share_src->share, src_name,
365 cli_share_dst->desthost, cli_share_dst->share, dst_name,
366 copy_acls ? "with" : "without",
367 copy_attrs ? "with" : "without",
368 copy_timestamps ? "(preserving timestamps)" : "" );
372 while (is_file) {
374 /* copying file */
375 int n, ret;
376 n = cli_read(cli_share_src, fnum_src, data, nread,
377 read_size);
379 if (n <= 0)
380 break;
382 ret = cli_write(cli_share_dst, fnum_dst, 0, data,
383 nread, n);
385 if (n != ret) {
386 d_fprintf(stderr, "Error writing file: %s\n",
387 cli_errstr(cli_share_dst));
388 nt_status = cli_nt_error(cli_share_dst);
389 goto out;
392 nread += n;
396 if (!is_file && !cli_chkpath(cli_share_dst, dst_name)) {
398 /* creating dir */
399 DEBUGADD(3,("creating dir %s on the destination server\n",
400 dst_name));
402 if (!cli_mkdir(cli_share_dst, dst_name)) {
403 DEBUG(0,("cannot create directory %s: %s\n",
404 dst_name, cli_errstr(cli_share_dst)));
405 nt_status = NT_STATUS_NO_SUCH_FILE;
408 if (!cli_chkpath(cli_share_dst, dst_name)) {
409 d_fprintf(stderr, "cannot check for directory %s: %s\n",
410 dst_name, cli_errstr(cli_share_dst));
411 goto out;
416 /* closing files */
417 if (!cli_close(cli_share_src, fnum_src)) {
418 d_fprintf(stderr, "could not close file on originating server: %s\n",
419 cli_errstr(cli_share_src));
420 nt_status = cli_nt_error(cli_share_src);
421 goto out;
424 if (is_file && !cli_close(cli_share_dst, fnum_dst)) {
425 d_fprintf(stderr, "could not close file on destination server: %s\n",
426 cli_errstr(cli_share_dst));
427 nt_status = cli_nt_error(cli_share_dst);
428 goto out;
431 /* possibly we have to copy some file-attributes / acls / sd */
432 nt_status = net_copy_fileattr(c, mem_ctx, cli_share_src, cli_share_dst,
433 src_name, dst_name, copy_acls,
434 copy_attrs, copy_timestamps, is_file);
435 if (!NT_STATUS_IS_OK(nt_status))
436 goto out;
439 nt_status = NT_STATUS_OK;
441 out:
443 /* cleaning up */
444 if (fnum_src)
445 cli_close(cli_share_src, fnum_src);
447 if (fnum_dst)
448 cli_close(cli_share_dst, fnum_dst);
450 SAFE_FREE(data);
452 return nt_status;
456 * Copy a driverfile from on connected share to another connected share
457 * This silently assumes that a driver-file is picked up from
459 * \\src_server\print$\{arch}\{version}\file
461 * and copied to
463 * \\dst_server\print$\{arch}\file
465 * to be added via setdriver-calls later.
466 * @param c A net_context structure
467 * @param mem_ctx A talloc-context
468 * @param cli_share_src A cli_state connected to source print$-share
469 * @param cli_share_dst A cli_state connected to destination print$-share
470 * @param file The file-name to be copied
471 * @param short_archi The name of the driver-architecture (short form)
473 * @return Normal NTSTATUS return.
476 static NTSTATUS net_copy_driverfile(struct net_context *c,
477 TALLOC_CTX *mem_ctx,
478 struct cli_state *cli_share_src,
479 struct cli_state *cli_share_dst,
480 const char *file, const char *short_archi) {
482 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
483 const char *p;
484 char *src_name;
485 char *dst_name;
486 char *version;
487 char *filename;
488 char *tok;
490 if (!file) {
491 return NT_STATUS_OK;
494 /* scroll through the file until we have the part
495 beyond archi_table.short_archi */
496 p = file;
497 while (next_token_talloc(mem_ctx, &p, &tok, "\\")) {
498 if (strequal(tok, short_archi)) {
499 next_token_talloc(mem_ctx, &p, &version, "\\");
500 next_token_talloc(mem_ctx, &p, &filename, "\\");
504 /* build source file name */
505 if (asprintf(&src_name, "\\%s\\%s\\%s", short_archi, version, filename) < 0 )
506 return NT_STATUS_NO_MEMORY;
509 /* create destination file name */
510 if (asprintf(&dst_name, "\\%s\\%s", short_archi, filename) < 0 )
511 return NT_STATUS_NO_MEMORY;
514 /* finally copy the file */
515 nt_status = net_copy_file(c, mem_ctx, cli_share_src, cli_share_dst,
516 src_name, dst_name, false, false, false, true);
517 if (!NT_STATUS_IS_OK(nt_status))
518 goto out;
520 nt_status = NT_STATUS_OK;
522 out:
523 SAFE_FREE(src_name);
524 SAFE_FREE(dst_name);
526 return nt_status;
530 * Check for existing Architecture directory on a given server
532 * @param cli_share A cli_state connected to a print$-share
533 * @param short_archi The Architecture for the print-driver
535 * @return Normal NTSTATUS return.
538 static NTSTATUS check_arch_dir(struct cli_state *cli_share, const char *short_archi)
541 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
542 char *dir;
544 if (asprintf(&dir, "\\%s", short_archi) < 0) {
545 return NT_STATUS_NO_MEMORY;
548 DEBUG(10,("creating print-driver dir for architecture: %s\n",
549 short_archi));
551 if (!cli_mkdir(cli_share, dir)) {
552 DEBUG(1,("cannot create directory %s: %s\n",
553 dir, cli_errstr(cli_share)));
554 nt_status = NT_STATUS_NO_SUCH_FILE;
557 if (!cli_chkpath(cli_share, dir)) {
558 d_fprintf(stderr, "cannot check %s: %s\n",
559 dir, cli_errstr(cli_share));
560 goto out;
563 nt_status = NT_STATUS_OK;
565 out:
566 SAFE_FREE(dir);
567 return nt_status;
571 * Copy a print-driver (level 3) from one connected print$-share to another
572 * connected print$-share
574 * @param c A net_context structure
575 * @param mem_ctx A talloc-context
576 * @param cli_share_src A cli_state connected to a print$-share
577 * @param cli_share_dst A cli_state connected to a print$-share
578 * @param short_archi The Architecture for the print-driver
579 * @param i1 The DRIVER_INFO_3-struct
581 * @return Normal NTSTATUS return.
584 static NTSTATUS copy_print_driver_3(struct net_context *c,
585 TALLOC_CTX *mem_ctx,
586 struct cli_state *cli_share_src,
587 struct cli_state *cli_share_dst,
588 const char *short_archi,
589 struct spoolss_DriverInfo3 *r)
591 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
592 int i;
594 if (r == NULL) {
595 return nt_status;
598 if (c->opt_verbose)
599 d_printf("copying driver: [%s], for architecture: [%s], version: [%d]\n",
600 r->driver_name, short_archi, r->version);
602 nt_status = net_copy_driverfile(c, mem_ctx, cli_share_src, cli_share_dst,
603 r->driver_path, short_archi);
604 if (!NT_STATUS_IS_OK(nt_status))
605 return nt_status;
607 nt_status = net_copy_driverfile(c, mem_ctx, cli_share_src, cli_share_dst,
608 r->data_file, short_archi);
609 if (!NT_STATUS_IS_OK(nt_status))
610 return nt_status;
612 nt_status = net_copy_driverfile(c, mem_ctx, cli_share_src, cli_share_dst,
613 r->config_file, short_archi);
614 if (!NT_STATUS_IS_OK(nt_status))
615 return nt_status;
617 nt_status = net_copy_driverfile(c, mem_ctx, cli_share_src, cli_share_dst,
618 r->help_file, short_archi);
619 if (!NT_STATUS_IS_OK(nt_status))
620 return nt_status;
622 for (i=0; r->dependent_files[i] != NULL; i++) {
624 nt_status = net_copy_driverfile(c, mem_ctx,
625 cli_share_src, cli_share_dst,
626 r->dependent_files[i], short_archi);
627 if (!NT_STATUS_IS_OK(nt_status)) {
628 return nt_status;
632 return NT_STATUS_OK;
636 * net_spoolss-functions
637 * =====================
639 * the net_spoolss-functions aim to simplify spoolss-client-functions
640 * required during the migration-process wrt buffer-sizes, returned
641 * error-codes, etc.
643 * this greatly reduces the complexitiy of the migrate-functions.
647 static bool net_spoolss_enum_printers(struct rpc_pipe_client *pipe_hnd,
648 TALLOC_CTX *mem_ctx,
649 char *name,
650 uint32_t flags,
651 uint32_t level,
652 uint32_t *num_printers,
653 union spoolss_PrinterInfo **info)
655 WERROR result;
657 /* enum printers */
659 result = rpccli_spoolss_enumprinters(pipe_hnd, mem_ctx,
660 flags,
661 name,
662 level,
664 num_printers,
665 info);
666 if (!W_ERROR_IS_OK(result)) {
667 printf("cannot enum printers: %s\n", win_errstr(result));
668 return false;
671 return true;
674 static bool net_spoolss_open_printer_ex(struct rpc_pipe_client *pipe_hnd,
675 TALLOC_CTX *mem_ctx,
676 const char *printername,
677 uint32_t access_required,
678 const char *username,
679 struct policy_handle *hnd)
681 WERROR result;
682 fstring printername2;
684 fstrcpy(printername2, pipe_hnd->srv_name_slash);
685 fstrcat(printername2, "\\");
686 fstrcat(printername2, printername);
688 DEBUG(10,("connecting to: %s as %s for %s and access: %x\n",
689 pipe_hnd->srv_name_slash, username, printername2, access_required));
691 /* open printer */
692 result = rpccli_spoolss_openprinter_ex(pipe_hnd, mem_ctx,
693 printername2,
694 access_required,
695 hnd);
697 /* be more verbose */
698 if (W_ERROR_V(result) == W_ERROR_V(WERR_ACCESS_DENIED)) {
699 d_fprintf(stderr, "no access to printer [%s] on [%s] for user [%s] granted\n",
700 printername2, pipe_hnd->srv_name_slash, username);
701 return false;
704 if (!W_ERROR_IS_OK(result)) {
705 d_fprintf(stderr, "cannot open printer %s on server %s: %s\n",
706 printername2, pipe_hnd->srv_name_slash, win_errstr(result));
707 return false;
710 DEBUG(2,("got printer handle for printer: %s, server: %s\n",
711 printername2, pipe_hnd->srv_name_slash));
713 return true;
716 static bool net_spoolss_getprinter(struct rpc_pipe_client *pipe_hnd,
717 TALLOC_CTX *mem_ctx,
718 struct policy_handle *hnd,
719 uint32_t level,
720 union spoolss_PrinterInfo *info)
722 WERROR result;
724 /* getprinter call */
725 result = rpccli_spoolss_getprinter(pipe_hnd, mem_ctx,
726 hnd,
727 level,
728 0, /* offered */
729 info);
730 if (!W_ERROR_IS_OK(result)) {
731 printf("cannot get printer-info: %s\n", win_errstr(result));
732 return false;
735 return true;
738 static bool net_spoolss_setprinter(struct rpc_pipe_client *pipe_hnd,
739 TALLOC_CTX *mem_ctx,
740 struct policy_handle *hnd,
741 uint32_t level,
742 union spoolss_PrinterInfo *info)
744 WERROR result;
745 NTSTATUS status;
746 struct spoolss_SetPrinterInfoCtr info_ctr;
747 struct spoolss_DevmodeContainer devmode_ctr;
748 struct sec_desc_buf secdesc_ctr;
750 ZERO_STRUCT(devmode_ctr);
751 ZERO_STRUCT(secdesc_ctr);
753 /* setprinter call */
755 info_ctr.level = level;
756 switch (level) {
757 case 0:
758 info_ctr.info.info0 = (struct spoolss_SetPrinterInfo0 *)&info->info0;
759 break;
760 case 1:
761 info_ctr.info.info1 = (struct spoolss_SetPrinterInfo1 *)&info->info1;
762 break;
763 case 2:
764 info_ctr.info.info2 = (struct spoolss_SetPrinterInfo2 *)&info->info2;
765 break;
766 case 3:
767 info_ctr.info.info3 = (struct spoolss_SetPrinterInfo3 *)&info->info3;
768 break;
769 case 4:
770 info_ctr.info.info4 = (struct spoolss_SetPrinterInfo4 *)&info->info4;
771 break;
772 case 5:
773 info_ctr.info.info5 = (struct spoolss_SetPrinterInfo5 *)&info->info5;
774 break;
775 case 6:
776 info_ctr.info.info6 = (struct spoolss_SetPrinterInfo6 *)&info->info6;
777 break;
778 case 7:
779 info_ctr.info.info7 = (struct spoolss_SetPrinterInfo7 *)&info->info7;
780 break;
781 #if 0 /* FIXME GD */
782 case 8:
783 info_ctr.info.info8 = (struct spoolss_SetPrinterInfo8 *)&info->info8;
784 break;
785 case 9:
786 info_ctr.info.info9 = (struct spoolss_SetPrinterInfo9 *)&info->info9;
787 break;
788 #endif
789 default:
790 break; /* FIXME */
793 status = rpccli_spoolss_SetPrinter(pipe_hnd, mem_ctx,
794 hnd,
795 &info_ctr,
796 &devmode_ctr,
797 &secdesc_ctr,
798 0, /* command */
799 &result);
801 if (!W_ERROR_IS_OK(result)) {
802 printf("cannot set printer-info: %s\n", win_errstr(result));
803 return false;
806 return true;
810 static bool net_spoolss_setprinterdata(struct rpc_pipe_client *pipe_hnd,
811 TALLOC_CTX *mem_ctx,
812 struct policy_handle *hnd,
813 const char *value_name,
814 enum winreg_Type type,
815 union spoolss_PrinterData data)
817 WERROR result;
818 NTSTATUS status;
820 /* setprinterdata call */
821 status = rpccli_spoolss_SetPrinterData(pipe_hnd, mem_ctx,
822 hnd,
823 value_name,
824 type,
825 data,
826 0, /* autocalculated */
827 &result);
829 if (!W_ERROR_IS_OK(result)) {
830 printf ("unable to set printerdata: %s\n", win_errstr(result));
831 return false;
834 return true;
838 static bool net_spoolss_enumprinterkey(struct rpc_pipe_client *pipe_hnd,
839 TALLOC_CTX *mem_ctx,
840 struct policy_handle *hnd,
841 const char *keyname,
842 const char ***keylist)
844 WERROR result;
846 /* enumprinterkey call */
847 result = rpccli_spoolss_enumprinterkey(pipe_hnd, mem_ctx, hnd, keyname, keylist, 0);
849 if (!W_ERROR_IS_OK(result)) {
850 printf("enumprinterkey failed: %s\n", win_errstr(result));
851 return false;
854 return true;
857 static bool net_spoolss_enumprinterdataex(struct rpc_pipe_client *pipe_hnd,
858 TALLOC_CTX *mem_ctx,
859 uint32_t offered,
860 struct policy_handle *hnd,
861 const char *keyname,
862 uint32_t *count,
863 struct spoolss_PrinterEnumValues **info)
865 WERROR result;
867 /* enumprinterdataex call */
868 result = rpccli_spoolss_enumprinterdataex(pipe_hnd, mem_ctx,
869 hnd,
870 keyname,
871 0, /* offered */
872 count,
873 info);
875 if (!W_ERROR_IS_OK(result)) {
876 printf("enumprinterdataex failed: %s\n", win_errstr(result));
877 return false;
880 return true;
884 static bool net_spoolss_setprinterdataex(struct rpc_pipe_client *pipe_hnd,
885 TALLOC_CTX *mem_ctx,
886 struct policy_handle *hnd,
887 const char *keyname,
888 REGISTRY_VALUE *value)
890 WERROR result;
891 NTSTATUS status;
893 /* setprinterdataex call */
894 status = rpccli_spoolss_SetPrinterDataEx(pipe_hnd, mem_ctx,
895 hnd,
896 keyname,
897 value->valuename,
898 value->type,
899 value->data_p,
900 value->size,
901 &result);
903 if (!W_ERROR_IS_OK(result)) {
904 printf("could not set printerdataex: %s\n", win_errstr(result));
905 return false;
908 return true;
911 static bool net_spoolss_enumforms(struct rpc_pipe_client *pipe_hnd,
912 TALLOC_CTX *mem_ctx,
913 struct policy_handle *hnd,
914 int level,
915 uint32_t *num_forms,
916 union spoolss_FormInfo **forms)
918 WERROR result;
920 /* enumforms call */
921 result = rpccli_spoolss_enumforms(pipe_hnd, mem_ctx,
922 hnd,
923 level,
925 num_forms,
926 forms);
927 if (!W_ERROR_IS_OK(result)) {
928 printf("could not enum forms: %s\n", win_errstr(result));
929 return false;
932 return true;
935 static bool net_spoolss_enumprinterdrivers (struct rpc_pipe_client *pipe_hnd,
936 TALLOC_CTX *mem_ctx,
937 uint32_t level, const char *env,
938 uint32_t *count,
939 union spoolss_DriverInfo **info)
941 WERROR result;
943 /* enumprinterdrivers call */
944 result = rpccli_spoolss_enumprinterdrivers(pipe_hnd, mem_ctx,
945 pipe_hnd->srv_name_slash,
946 env,
947 level,
949 count,
950 info);
951 if (!W_ERROR_IS_OK(result)) {
952 printf("cannot enum drivers: %s\n", win_errstr(result));
953 return false;
956 return true;
959 static bool net_spoolss_getprinterdriver(struct rpc_pipe_client *pipe_hnd,
960 TALLOC_CTX *mem_ctx,
961 struct policy_handle *hnd, uint32_t level,
962 const char *env, int version,
963 union spoolss_DriverInfo *info)
965 WERROR result;
966 uint32_t server_major_version;
967 uint32_t server_minor_version;
969 /* getprinterdriver call */
970 result = rpccli_spoolss_getprinterdriver2(pipe_hnd, mem_ctx,
971 hnd,
972 env,
973 level,
975 version,
977 info,
978 &server_major_version,
979 &server_minor_version);
980 if (!W_ERROR_IS_OK(result)) {
981 DEBUG(1,("cannot get driver (for architecture: %s): %s\n",
982 env, win_errstr(result)));
983 if (W_ERROR_V(result) != W_ERROR_V(WERR_UNKNOWN_PRINTER_DRIVER) &&
984 W_ERROR_V(result) != W_ERROR_V(WERR_INVALID_ENVIRONMENT)) {
985 printf("cannot get driver: %s\n", win_errstr(result));
987 return false;
990 return true;
994 static bool net_spoolss_addprinterdriver(struct rpc_pipe_client *pipe_hnd,
995 TALLOC_CTX *mem_ctx, uint32_t level,
996 union spoolss_DriverInfo *info)
998 WERROR result;
999 NTSTATUS status;
1000 struct spoolss_AddDriverInfoCtr info_ctr;
1002 info_ctr.level = level;
1004 switch (level) {
1005 case 2:
1006 info_ctr.info.info2 = (struct spoolss_AddDriverInfo2 *)&info->info2;
1007 break;
1008 case 3:
1009 info_ctr.info.info3 = (struct spoolss_AddDriverInfo3 *)&info->info3;
1010 break;
1011 default:
1012 printf("unsupported info level: %d\n", level);
1013 return false;
1016 /* addprinterdriver call */
1017 status = rpccli_spoolss_AddPrinterDriver(pipe_hnd, mem_ctx,
1018 pipe_hnd->srv_name_slash,
1019 &info_ctr,
1020 &result);
1021 /* be more verbose */
1022 if (W_ERROR_V(result) == W_ERROR_V(WERR_ACCESS_DENIED)) {
1023 printf("You are not allowed to add drivers\n");
1024 return false;
1026 if (!W_ERROR_IS_OK(result)) {
1027 printf("cannot add driver: %s\n", win_errstr(result));
1028 return false;
1031 return true;
1035 * abstraction function to get uint32_t num_printers and PRINTER_INFO_CTR ctr
1036 * for a single printer or for all printers depending on argc/argv
1039 static bool get_printer_info(struct rpc_pipe_client *pipe_hnd,
1040 TALLOC_CTX *mem_ctx,
1041 int level,
1042 int argc,
1043 const char **argv,
1044 uint32_t *num_printers,
1045 union spoolss_PrinterInfo **info_p)
1047 struct policy_handle hnd;
1049 /* no arguments given, enumerate all printers */
1050 if (argc == 0) {
1052 if (!net_spoolss_enum_printers(pipe_hnd, mem_ctx, NULL,
1053 PRINTER_ENUM_LOCAL|PRINTER_ENUM_SHARED,
1054 level, num_printers, info_p))
1055 return false;
1057 goto out;
1060 /* argument given, get a single printer by name */
1061 if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, argv[0],
1062 MAXIMUM_ALLOWED_ACCESS,
1063 pipe_hnd->auth->user_name,
1064 &hnd))
1065 return false;
1067 if (!net_spoolss_getprinter(pipe_hnd, mem_ctx, &hnd, level, *info_p)) {
1068 rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd, NULL);
1069 return false;
1072 rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd, NULL);
1074 *num_printers = 1;
1076 out:
1077 DEBUG(3,("got %d printers\n", *num_printers));
1079 return true;
1084 * List print-queues (including local printers that are not shared)
1086 * All parameters are provided by the run_rpc_command function, except for
1087 * argc, argv which are passed through.
1089 * @param c A net_context structure
1090 * @param domain_sid The domain sid aquired from the remote server
1091 * @param cli A cli_state connected to the server.
1092 * @param mem_ctx Talloc context, destoyed on compleation of the function.
1093 * @param argc Standard main() style argc
1094 * @param argv Standard main() style argv. Initial components are already
1095 * stripped
1097 * @return Normal NTSTATUS return.
1100 NTSTATUS rpc_printer_list_internals(struct net_context *c,
1101 const DOM_SID *domain_sid,
1102 const char *domain_name,
1103 struct cli_state *cli,
1104 struct rpc_pipe_client *pipe_hnd,
1105 TALLOC_CTX *mem_ctx,
1106 int argc,
1107 const char **argv)
1109 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1110 uint32_t i, num_printers;
1111 uint32_t level = 2;
1112 const char *printername, *sharename;
1113 union spoolss_PrinterInfo *info;
1115 printf("listing printers\n");
1117 if (!get_printer_info(pipe_hnd, mem_ctx, level, argc, argv, &num_printers, &info))
1118 return nt_status;
1120 for (i = 0; i < num_printers; i++) {
1122 /* do some initialization */
1123 printername = info[i].info2.printername;
1124 sharename = info[i].info2.sharename;
1126 if (printername && sharename) {
1127 d_printf("printer %d: %s, shared as: %s\n",
1128 i+1, printername, sharename);
1132 return NT_STATUS_OK;
1136 * List printer-drivers from a server
1138 * All parameters are provided by the run_rpc_command function, except for
1139 * argc, argv which are passed through.
1141 * @param c A net_context structure
1142 * @param domain_sid The domain sid aquired from the remote server
1143 * @param cli A cli_state connected to the server.
1144 * @param mem_ctx Talloc context, destoyed on compleation of the function.
1145 * @param argc Standard main() style argc
1146 * @param argv Standard main() style argv. Initial components are already
1147 * stripped
1149 * @return Normal NTSTATUS return.
1152 NTSTATUS rpc_printer_driver_list_internals(struct net_context *c,
1153 const DOM_SID *domain_sid,
1154 const char *domain_name,
1155 struct cli_state *cli,
1156 struct rpc_pipe_client *pipe_hnd,
1157 TALLOC_CTX *mem_ctx,
1158 int argc,
1159 const char **argv)
1161 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1162 uint32_t i;
1163 uint32_t level = 3;
1164 union spoolss_DriverInfo *info;
1165 int d;
1167 printf("listing printer-drivers\n");
1169 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1171 uint32_t num_drivers;
1173 /* enum remote drivers */
1174 if (!net_spoolss_enumprinterdrivers(pipe_hnd, mem_ctx, level,
1175 archi_table[i].long_archi,
1176 &num_drivers, &info)) {
1177 nt_status = NT_STATUS_UNSUCCESSFUL;
1178 goto done;
1181 if (num_drivers == 0) {
1182 d_printf ("no drivers found on server for architecture: [%s].\n",
1183 archi_table[i].long_archi);
1184 continue;
1187 d_printf("got %d printer-drivers for architecture: [%s]\n",
1188 num_drivers, archi_table[i].long_archi);
1191 /* do something for all drivers for architecture */
1192 for (d = 0; d < num_drivers; d++) {
1193 display_print_driver3(&info[d].info3);
1197 nt_status = NT_STATUS_OK;
1199 done:
1200 return nt_status;
1205 * Publish print-queues with args-wrapper
1207 * @param cli A cli_state connected to the server.
1208 * @param mem_ctx Talloc context, destoyed on compleation of the function.
1209 * @param argc Standard main() style argc
1210 * @param argv Standard main() style argv. Initial components are already
1211 * stripped
1212 * @param action
1214 * @return Normal NTSTATUS return.
1217 static NTSTATUS rpc_printer_publish_internals_args(struct rpc_pipe_client *pipe_hnd,
1218 TALLOC_CTX *mem_ctx,
1219 int argc,
1220 const char **argv,
1221 uint32_t action)
1223 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1224 uint32_t i, num_printers;
1225 uint32_t level = 7;
1226 const char *printername, *sharename;
1227 union spoolss_PrinterInfo *info_enum;
1228 union spoolss_PrinterInfo info;
1229 struct spoolss_SetPrinterInfoCtr info_ctr;
1230 struct spoolss_DevmodeContainer devmode_ctr;
1231 struct sec_desc_buf secdesc_ctr;
1232 struct policy_handle hnd;
1233 WERROR result;
1234 const char *action_str;
1236 if (!get_printer_info(pipe_hnd, mem_ctx, 2, argc, argv, &num_printers, &info_enum))
1237 return nt_status;
1239 for (i = 0; i < num_printers; i++) {
1241 /* do some initialization */
1242 printername = info_enum[i].info2.printername;
1243 sharename = info_enum[i].info2.sharename;
1244 if (!printername || !sharename) {
1245 goto done;
1248 /* open printer handle */
1249 if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, sharename,
1250 PRINTER_ALL_ACCESS, pipe_hnd->auth->user_name, &hnd))
1251 goto done;
1253 /* check for existing dst printer */
1254 if (!net_spoolss_getprinter(pipe_hnd, mem_ctx, &hnd, level, &info))
1255 goto done;
1257 /* check action and set string */
1258 switch (action) {
1259 case DSPRINT_PUBLISH:
1260 action_str = "published";
1261 break;
1262 case DSPRINT_UPDATE:
1263 action_str = "updated";
1264 break;
1265 case DSPRINT_UNPUBLISH:
1266 action_str = "unpublished";
1267 break;
1268 default:
1269 action_str = "unknown action";
1270 printf("unkown action: %d\n", action);
1271 break;
1274 info.info7.action = action;
1275 info_ctr.level = 7;
1276 info_ctr.info.info7 = (struct spoolss_SetPrinterInfo7 *)&info.info7;
1278 ZERO_STRUCT(devmode_ctr);
1279 ZERO_STRUCT(secdesc_ctr);
1281 nt_status = rpccli_spoolss_SetPrinter(pipe_hnd, mem_ctx,
1282 &hnd,
1283 &info_ctr,
1284 &devmode_ctr,
1285 &secdesc_ctr,
1286 0, /* command */
1287 &result);
1289 if (!W_ERROR_IS_OK(result) && (W_ERROR_V(result) != W_ERROR_V(WERR_IO_PENDING))) {
1290 printf("cannot set printer-info: %s\n", win_errstr(result));
1291 goto done;
1294 printf("successfully %s printer %s in Active Directory\n", action_str, sharename);
1297 nt_status = NT_STATUS_OK;
1299 done:
1300 if (is_valid_policy_hnd(&hnd))
1301 rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd, NULL);
1303 return nt_status;
1306 NTSTATUS rpc_printer_publish_publish_internals(struct net_context *c,
1307 const DOM_SID *domain_sid,
1308 const char *domain_name,
1309 struct cli_state *cli,
1310 struct rpc_pipe_client *pipe_hnd,
1311 TALLOC_CTX *mem_ctx,
1312 int argc,
1313 const char **argv)
1315 return rpc_printer_publish_internals_args(pipe_hnd, mem_ctx, argc, argv, DSPRINT_PUBLISH);
1318 NTSTATUS rpc_printer_publish_unpublish_internals(struct net_context *c,
1319 const DOM_SID *domain_sid,
1320 const char *domain_name,
1321 struct cli_state *cli,
1322 struct rpc_pipe_client *pipe_hnd,
1323 TALLOC_CTX *mem_ctx,
1324 int argc,
1325 const char **argv)
1327 return rpc_printer_publish_internals_args(pipe_hnd, mem_ctx, argc, argv, DSPRINT_UNPUBLISH);
1330 NTSTATUS rpc_printer_publish_update_internals(struct net_context *c,
1331 const DOM_SID *domain_sid,
1332 const char *domain_name,
1333 struct cli_state *cli,
1334 struct rpc_pipe_client *pipe_hnd,
1335 TALLOC_CTX *mem_ctx,
1336 int argc,
1337 const char **argv)
1339 return rpc_printer_publish_internals_args(pipe_hnd, mem_ctx, argc, argv, DSPRINT_UPDATE);
1343 * List print-queues w.r.t. their publishing state
1345 * All parameters are provided by the run_rpc_command function, except for
1346 * argc, argv which are passed through.
1348 * @param c A net_context structure
1349 * @param domain_sid The domain sid aquired from the remote server
1350 * @param cli A cli_state connected to the server.
1351 * @param mem_ctx Talloc context, destoyed on compleation of the function.
1352 * @param argc Standard main() style argc
1353 * @param argv Standard main() style argv. Initial components are already
1354 * stripped
1356 * @return Normal NTSTATUS return.
1359 NTSTATUS rpc_printer_publish_list_internals(struct net_context *c,
1360 const DOM_SID *domain_sid,
1361 const char *domain_name,
1362 struct cli_state *cli,
1363 struct rpc_pipe_client *pipe_hnd,
1364 TALLOC_CTX *mem_ctx,
1365 int argc,
1366 const char **argv)
1368 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1369 uint32_t i, num_printers;
1370 uint32_t level = 7;
1371 const char *printername, *sharename;
1372 union spoolss_PrinterInfo *info_enum;
1373 union spoolss_PrinterInfo info;
1374 struct policy_handle hnd;
1375 int state;
1377 if (!get_printer_info(pipe_hnd, mem_ctx, 2, argc, argv, &num_printers, &info_enum))
1378 return nt_status;
1380 for (i = 0; i < num_printers; i++) {
1382 /* do some initialization */
1383 printername = info_enum[i].info2.printername;
1384 sharename = info_enum[i].info2.sharename;
1386 if (!printername || !sharename) {
1387 goto done;
1390 /* open printer handle */
1391 if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, sharename,
1392 PRINTER_ALL_ACCESS, cli->user_name, &hnd))
1393 goto done;
1395 /* check for existing dst printer */
1396 if (!net_spoolss_getprinter(pipe_hnd, mem_ctx, &hnd, level, &info))
1397 goto done;
1399 if (!info.info7.guid) {
1400 goto done;
1402 state = info.info7.action;
1403 switch (state) {
1404 case DSPRINT_PUBLISH:
1405 printf("printer [%s] is published", sharename);
1406 if (c->opt_verbose)
1407 printf(", guid: %s", info.info7.guid);
1408 printf("\n");
1409 break;
1410 case DSPRINT_UNPUBLISH:
1411 printf("printer [%s] is unpublished\n", sharename);
1412 break;
1413 case DSPRINT_UPDATE:
1414 printf("printer [%s] is currently updating\n", sharename);
1415 break;
1416 default:
1417 printf("unkown state: %d\n", state);
1418 break;
1422 nt_status = NT_STATUS_OK;
1424 done:
1425 if (is_valid_policy_hnd(&hnd))
1426 rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd, NULL);
1428 return nt_status;
1432 * Migrate Printer-ACLs from a source server to the destination server
1434 * All parameters are provided by the run_rpc_command function, except for
1435 * argc, argv which are passed through.
1437 * @param c A net_context structure
1438 * @param domain_sid The domain sid aquired from the remote server
1439 * @param cli A cli_state connected to the server.
1440 * @param mem_ctx Talloc context, destoyed on compleation of the function.
1441 * @param argc Standard main() style argc
1442 * @param argv Standard main() style argv. Initial components are already
1443 * stripped
1445 * @return Normal NTSTATUS return.
1448 NTSTATUS rpc_printer_migrate_security_internals(struct net_context *c,
1449 const DOM_SID *domain_sid,
1450 const char *domain_name,
1451 struct cli_state *cli,
1452 struct rpc_pipe_client *pipe_hnd,
1453 TALLOC_CTX *mem_ctx,
1454 int argc,
1455 const char **argv)
1457 /* TODO: what now, info2 or info3 ?
1458 convince jerry that we should add clientside setacls level 3 at least
1460 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1461 uint32_t i = 0;
1462 uint32_t num_printers;
1463 uint32_t level = 2;
1464 const char *printername, *sharename;
1465 struct rpc_pipe_client *pipe_hnd_dst = NULL;
1466 struct policy_handle hnd_src, hnd_dst;
1467 union spoolss_PrinterInfo *info_enum;
1468 struct cli_state *cli_dst = NULL;
1469 union spoolss_PrinterInfo info_src, info_dst;
1471 DEBUG(3,("copying printer ACLs\n"));
1473 /* connect destination PI_SPOOLSS */
1474 nt_status = connect_dst_pipe(c, &cli_dst, &pipe_hnd_dst,
1475 &ndr_table_spoolss.syntax_id);
1476 if (!NT_STATUS_IS_OK(nt_status))
1477 return nt_status;
1480 /* enum source printers */
1481 if (!get_printer_info(pipe_hnd, mem_ctx, level, argc, argv, &num_printers, &info_enum)) {
1482 nt_status = NT_STATUS_UNSUCCESSFUL;
1483 goto done;
1486 if (!num_printers) {
1487 printf ("no printers found on server.\n");
1488 nt_status = NT_STATUS_OK;
1489 goto done;
1492 /* do something for all printers */
1493 for (i = 0; i < num_printers; i++) {
1495 /* do some initialization */
1496 printername = info_enum[i].info2.printername;
1497 sharename = info_enum[i].info2.sharename;
1499 if (!printername || !sharename) {
1500 nt_status = NT_STATUS_UNSUCCESSFUL;
1501 goto done;
1504 /* we can reset NT_STATUS here because we do not
1505 get any real NT_STATUS-codes anymore from now on */
1506 nt_status = NT_STATUS_UNSUCCESSFUL;
1508 d_printf("migrating printer ACLs for: [%s] / [%s]\n",
1509 printername, sharename);
1511 /* according to msdn you have specify these access-rights
1512 to see the security descriptor
1513 - READ_CONTROL (DACL)
1514 - ACCESS_SYSTEM_SECURITY (SACL)
1517 /* open src printer handle */
1518 if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, sharename,
1519 MAXIMUM_ALLOWED_ACCESS, cli->user_name, &hnd_src))
1520 goto done;
1522 /* open dst printer handle */
1523 if (!net_spoolss_open_printer_ex(pipe_hnd_dst, mem_ctx, sharename,
1524 PRINTER_ALL_ACCESS, cli_dst->user_name, &hnd_dst))
1525 goto done;
1527 /* check for existing dst printer */
1528 if (!net_spoolss_getprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, level, &info_dst))
1529 goto done;
1531 /* check for existing src printer */
1532 if (!net_spoolss_getprinter(pipe_hnd, mem_ctx, &hnd_src, 3, &info_src))
1533 goto done;
1535 /* Copy Security Descriptor */
1537 /* copy secdesc (info level 2) */
1538 info_dst.info2.devmode = NULL;
1539 info_dst.info2.secdesc = dup_sec_desc(mem_ctx, info_src.info3.secdesc);
1541 if (c->opt_verbose)
1542 display_sec_desc(info_dst.info2.secdesc);
1544 if (!net_spoolss_setprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, 2, &info_dst))
1545 goto done;
1547 DEBUGADD(1,("\tSetPrinter of SECDESC succeeded\n"));
1550 /* close printer handles here */
1551 if (is_valid_policy_hnd(&hnd_src)) {
1552 rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd_src, NULL);
1555 if (is_valid_policy_hnd(&hnd_dst)) {
1556 rpccli_spoolss_ClosePrinter(pipe_hnd_dst, mem_ctx, &hnd_dst, NULL);
1561 nt_status = NT_STATUS_OK;
1563 done:
1565 if (is_valid_policy_hnd(&hnd_src)) {
1566 rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd_src, NULL);
1569 if (is_valid_policy_hnd(&hnd_dst)) {
1570 rpccli_spoolss_ClosePrinter(pipe_hnd_dst, mem_ctx, &hnd_dst, NULL);
1573 if (cli_dst) {
1574 cli_shutdown(cli_dst);
1576 return nt_status;
1580 * Migrate printer-forms from a src server to the dst server
1582 * All parameters are provided by the run_rpc_command function, except for
1583 * argc, argv which are passed through.
1585 * @param c A net_context structure
1586 * @param domain_sid The domain sid aquired from the remote server
1587 * @param cli A cli_state connected to the server.
1588 * @param mem_ctx Talloc context, destoyed on compleation of the function.
1589 * @param argc Standard main() style argc
1590 * @param argv Standard main() style argv. Initial components are already
1591 * stripped
1593 * @return Normal NTSTATUS return.
1596 NTSTATUS rpc_printer_migrate_forms_internals(struct net_context *c,
1597 const DOM_SID *domain_sid,
1598 const char *domain_name,
1599 struct cli_state *cli,
1600 struct rpc_pipe_client *pipe_hnd,
1601 TALLOC_CTX *mem_ctx,
1602 int argc,
1603 const char **argv)
1605 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1606 WERROR result;
1607 uint32_t i, f;
1608 uint32_t num_printers;
1609 uint32_t level = 1;
1610 const char *printername, *sharename;
1611 struct rpc_pipe_client *pipe_hnd_dst = NULL;
1612 struct policy_handle hnd_src, hnd_dst;
1613 union spoolss_PrinterInfo *info_enum;
1614 union spoolss_PrinterInfo info_dst;
1615 uint32_t num_forms;
1616 union spoolss_FormInfo *forms;
1617 struct cli_state *cli_dst = NULL;
1619 DEBUG(3,("copying forms\n"));
1621 /* connect destination PI_SPOOLSS */
1622 nt_status = connect_dst_pipe(c, &cli_dst, &pipe_hnd_dst,
1623 &ndr_table_spoolss.syntax_id);
1624 if (!NT_STATUS_IS_OK(nt_status))
1625 return nt_status;
1627 /* enum src printers */
1628 if (!get_printer_info(pipe_hnd, mem_ctx, 2, argc, argv, &num_printers, &info_enum)) {
1629 nt_status = NT_STATUS_UNSUCCESSFUL;
1630 goto done;
1633 if (!num_printers) {
1634 printf ("no printers found on server.\n");
1635 nt_status = NT_STATUS_OK;
1636 goto done;
1639 /* do something for all printers */
1640 for (i = 0; i < num_printers; i++) {
1642 /* do some initialization */
1643 printername = info_enum[i].info2.printername;
1644 sharename = info_enum[i].info2.sharename;
1646 if (!printername || !sharename) {
1647 nt_status = NT_STATUS_UNSUCCESSFUL;
1648 goto done;
1650 /* we can reset NT_STATUS here because we do not
1651 get any real NT_STATUS-codes anymore from now on */
1652 nt_status = NT_STATUS_UNSUCCESSFUL;
1654 d_printf("migrating printer forms for: [%s] / [%s]\n",
1655 printername, sharename);
1658 /* open src printer handle */
1659 if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, sharename,
1660 MAXIMUM_ALLOWED_ACCESS, cli->user_name, &hnd_src))
1661 goto done;
1663 /* open dst printer handle */
1664 if (!net_spoolss_open_printer_ex(pipe_hnd_dst, mem_ctx, sharename,
1665 PRINTER_ALL_ACCESS, cli->user_name, &hnd_dst))
1666 goto done;
1668 /* check for existing dst printer */
1669 if (!net_spoolss_getprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, level, &info_dst))
1670 goto done;
1672 /* finally migrate forms */
1673 if (!net_spoolss_enumforms(pipe_hnd, mem_ctx, &hnd_src, level, &num_forms, &forms))
1674 goto done;
1676 DEBUG(1,("got %d forms for printer\n", num_forms));
1679 for (f = 0; f < num_forms; f++) {
1681 union spoolss_AddFormInfo info;
1682 NTSTATUS status;
1684 /* only migrate FORM_PRINTER types, according to jerry
1685 FORM_BUILTIN-types are hard-coded in samba */
1686 if (forms[f].info1.flags != SPOOLSS_FORM_PRINTER)
1687 continue;
1689 if (c->opt_verbose)
1690 d_printf("\tmigrating form # %d [%s] of type [%d]\n",
1691 f, forms[f].info1.form_name,
1692 forms[f].info1.flags);
1694 info.info1 = (struct spoolss_AddFormInfo1 *)&forms[f].info1;
1696 /* FIXME: there might be something wrong with samba's
1697 builtin-forms */
1698 status = rpccli_spoolss_AddForm(pipe_hnd_dst, mem_ctx,
1699 &hnd_dst,
1701 info,
1702 &result);
1703 if (!W_ERROR_IS_OK(result)) {
1704 d_printf("\tAddForm form %d: [%s] refused.\n",
1705 f, forms[f].info1.form_name);
1706 continue;
1709 DEBUGADD(1,("\tAddForm of [%s] succeeded\n",
1710 forms[f].info1.form_name));
1714 /* close printer handles here */
1715 if (is_valid_policy_hnd(&hnd_src)) {
1716 rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd_src, NULL);
1719 if (is_valid_policy_hnd(&hnd_dst)) {
1720 rpccli_spoolss_ClosePrinter(pipe_hnd_dst, mem_ctx, &hnd_dst, NULL);
1724 nt_status = NT_STATUS_OK;
1726 done:
1728 if (is_valid_policy_hnd(&hnd_src))
1729 rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd_src, NULL);
1731 if (is_valid_policy_hnd(&hnd_dst))
1732 rpccli_spoolss_ClosePrinter(pipe_hnd_dst, mem_ctx, &hnd_dst, NULL);
1734 if (cli_dst) {
1735 cli_shutdown(cli_dst);
1737 return nt_status;
1741 * Migrate printer-drivers from a src server to the dst server
1743 * All parameters are provided by the run_rpc_command function, except for
1744 * argc, argv which are passed through.
1746 * @param c A net_context structure
1747 * @param domain_sid The domain sid aquired from the remote server
1748 * @param cli A cli_state connected to the server.
1749 * @param mem_ctx Talloc context, destoyed on compleation of the function.
1750 * @param argc Standard main() style argc
1751 * @param argv Standard main() style argv. Initial components are already
1752 * stripped
1754 * @return Normal NTSTATUS return.
1757 NTSTATUS rpc_printer_migrate_drivers_internals(struct net_context *c,
1758 const DOM_SID *domain_sid,
1759 const char *domain_name,
1760 struct cli_state *cli,
1761 struct rpc_pipe_client *pipe_hnd,
1762 TALLOC_CTX *mem_ctx,
1763 int argc,
1764 const char **argv)
1766 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1767 uint32_t i, p;
1768 uint32_t num_printers;
1769 uint32_t level = 3;
1770 const char *printername, *sharename;
1771 bool got_src_driver_share = false;
1772 bool got_dst_driver_share = false;
1773 struct rpc_pipe_client *pipe_hnd_dst = NULL;
1774 struct policy_handle hnd_src, hnd_dst;
1775 union spoolss_DriverInfo drv_info_src;
1776 union spoolss_PrinterInfo *info_enum;
1777 union spoolss_PrinterInfo info_dst;
1778 struct cli_state *cli_dst = NULL;
1779 struct cli_state *cli_share_src = NULL;
1780 struct cli_state *cli_share_dst = NULL;
1781 const char *drivername = NULL;
1783 DEBUG(3,("copying printer-drivers\n"));
1785 nt_status = connect_dst_pipe(c, &cli_dst, &pipe_hnd_dst,
1786 &ndr_table_spoolss.syntax_id);
1787 if (!NT_STATUS_IS_OK(nt_status))
1788 return nt_status;
1790 /* open print$-share on the src server */
1791 nt_status = connect_to_service(c, &cli_share_src, &cli->dest_ss,
1792 cli->desthost, "print$", "A:");
1793 if (!NT_STATUS_IS_OK(nt_status))
1794 goto done;
1796 got_src_driver_share = true;
1799 /* open print$-share on the dst server */
1800 nt_status = connect_to_service(c, &cli_share_dst, &cli_dst->dest_ss,
1801 cli_dst->desthost, "print$", "A:");
1802 if (!NT_STATUS_IS_OK(nt_status))
1803 return nt_status;
1805 got_dst_driver_share = true;
1808 /* enum src printers */
1809 if (!get_printer_info(pipe_hnd, mem_ctx, 2, argc, argv, &num_printers, &info_enum)) {
1810 nt_status = NT_STATUS_UNSUCCESSFUL;
1811 goto done;
1814 if (num_printers == 0) {
1815 printf ("no printers found on server.\n");
1816 nt_status = NT_STATUS_OK;
1817 goto done;
1821 /* do something for all printers */
1822 for (p = 0; p < num_printers; p++) {
1824 /* do some initialization */
1825 printername = info_enum[p].info2.printername;
1826 sharename = info_enum[p].info2.sharename;
1828 if (!printername || !sharename) {
1829 nt_status = NT_STATUS_UNSUCCESSFUL;
1830 goto done;
1833 /* we can reset NT_STATUS here because we do not
1834 get any real NT_STATUS-codes anymore from now on */
1835 nt_status = NT_STATUS_UNSUCCESSFUL;
1837 d_printf("migrating printer driver for: [%s] / [%s]\n",
1838 printername, sharename);
1840 /* open dst printer handle */
1841 if (!net_spoolss_open_printer_ex(pipe_hnd_dst, mem_ctx, sharename,
1842 PRINTER_ALL_ACCESS, cli->user_name, &hnd_dst))
1843 goto done;
1845 /* check for existing dst printer */
1846 if (!net_spoolss_getprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, 2, &info_dst))
1847 goto done;
1850 /* open src printer handle */
1851 if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, sharename,
1852 MAXIMUM_ALLOWED_ACCESS,
1853 pipe_hnd->auth->user_name,
1854 &hnd_src))
1855 goto done;
1857 /* in a first step call getdriver for each shared printer (per arch)
1858 to get a list of all files that have to be copied */
1860 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1862 /* getdriver src */
1863 if (!net_spoolss_getprinterdriver(pipe_hnd, mem_ctx, &hnd_src,
1864 level, archi_table[i].long_archi,
1865 archi_table[i].version, &drv_info_src))
1866 continue;
1868 drivername = drv_info_src.info3.driver_name;
1870 if (c->opt_verbose)
1871 display_print_driver3(&drv_info_src.info3);
1873 /* check arch dir */
1874 nt_status = check_arch_dir(cli_share_dst, archi_table[i].short_archi);
1875 if (!NT_STATUS_IS_OK(nt_status))
1876 goto done;
1879 /* copy driver-files */
1880 nt_status = copy_print_driver_3(c, mem_ctx, cli_share_src, cli_share_dst,
1881 archi_table[i].short_archi,
1882 &drv_info_src.info3);
1883 if (!NT_STATUS_IS_OK(nt_status))
1884 goto done;
1887 /* adddriver dst */
1888 if (!net_spoolss_addprinterdriver(pipe_hnd_dst, mem_ctx, level, &drv_info_src)) {
1889 nt_status = NT_STATUS_UNSUCCESSFUL;
1890 goto done;
1893 DEBUGADD(1,("Sucessfully added driver [%s] for printer [%s]\n",
1894 drivername, printername));
1898 if (!drivername || strlen(drivername) == 0) {
1899 DEBUGADD(1,("Did not get driver for printer %s\n",
1900 printername));
1901 goto done;
1904 /* setdriver dst */
1905 info_dst.info2.drivername = drivername;
1907 if (!net_spoolss_setprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, 2, &info_dst)) {
1908 nt_status = NT_STATUS_UNSUCCESSFUL;
1909 goto done;
1912 DEBUGADD(1,("Sucessfully set driver %s for printer %s\n",
1913 drivername, printername));
1915 /* close dst */
1916 if (is_valid_policy_hnd(&hnd_dst)) {
1917 rpccli_spoolss_ClosePrinter(pipe_hnd_dst, mem_ctx, &hnd_dst, NULL);
1920 /* close src */
1921 if (is_valid_policy_hnd(&hnd_src)) {
1922 rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd_src, NULL);
1926 nt_status = NT_STATUS_OK;
1928 done:
1930 if (is_valid_policy_hnd(&hnd_src))
1931 rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd_src, NULL);
1933 if (is_valid_policy_hnd(&hnd_dst))
1934 rpccli_spoolss_ClosePrinter(pipe_hnd_dst, mem_ctx, &hnd_dst, NULL);
1936 if (cli_dst) {
1937 cli_shutdown(cli_dst);
1940 if (got_src_driver_share)
1941 cli_shutdown(cli_share_src);
1943 if (got_dst_driver_share)
1944 cli_shutdown(cli_share_dst);
1946 return nt_status;
1951 * Migrate printer-queues from a src to the dst server
1952 * (requires a working "addprinter command" to be installed for the local smbd)
1954 * All parameters are provided by the run_rpc_command function, except for
1955 * argc, argv which are passed through.
1957 * @param c A net_context structure
1958 * @param domain_sid The domain sid aquired from the remote server
1959 * @param cli A cli_state connected to the server.
1960 * @param mem_ctx Talloc context, destoyed on compleation of the function.
1961 * @param argc Standard main() style argc
1962 * @param argv Standard main() style argv. Initial components are already
1963 * stripped
1965 * @return Normal NTSTATUS return.
1968 NTSTATUS rpc_printer_migrate_printers_internals(struct net_context *c,
1969 const DOM_SID *domain_sid,
1970 const char *domain_name,
1971 struct cli_state *cli,
1972 struct rpc_pipe_client *pipe_hnd,
1973 TALLOC_CTX *mem_ctx,
1974 int argc,
1975 const char **argv)
1977 WERROR result;
1978 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1979 uint32_t i = 0, num_printers;
1980 uint32_t level = 2;
1981 union spoolss_PrinterInfo info_dst, info_src;
1982 union spoolss_PrinterInfo *info_enum;
1983 struct cli_state *cli_dst = NULL;
1984 struct policy_handle hnd_dst, hnd_src;
1985 const char *printername, *sharename;
1986 struct rpc_pipe_client *pipe_hnd_dst = NULL;
1987 struct spoolss_SetPrinterInfoCtr info_ctr;
1989 DEBUG(3,("copying printers\n"));
1991 /* connect destination PI_SPOOLSS */
1992 nt_status = connect_dst_pipe(c, &cli_dst, &pipe_hnd_dst,
1993 &ndr_table_spoolss.syntax_id);
1994 if (!NT_STATUS_IS_OK(nt_status))
1995 return nt_status;
1997 /* enum printers */
1998 if (!get_printer_info(pipe_hnd, mem_ctx, level, argc, argv, &num_printers, &info_enum)) {
1999 nt_status = NT_STATUS_UNSUCCESSFUL;
2000 goto done;
2003 if (!num_printers) {
2004 printf ("no printers found on server.\n");
2005 nt_status = NT_STATUS_OK;
2006 goto done;
2009 /* do something for all printers */
2010 for (i = 0; i < num_printers; i++) {
2012 /* do some initialization */
2013 printername = info_enum[i].info2.printername;
2014 sharename = info_enum[i].info2.sharename;
2016 if (!printername || !sharename) {
2017 nt_status = NT_STATUS_UNSUCCESSFUL;
2018 goto done;
2020 /* we can reset NT_STATUS here because we do not
2021 get any real NT_STATUS-codes anymore from now on */
2022 nt_status = NT_STATUS_UNSUCCESSFUL;
2024 d_printf("migrating printer queue for: [%s] / [%s]\n",
2025 printername, sharename);
2027 /* open dst printer handle */
2028 if (!net_spoolss_open_printer_ex(pipe_hnd_dst, mem_ctx, sharename,
2029 PRINTER_ALL_ACCESS, cli->user_name, &hnd_dst)) {
2031 DEBUG(1,("could not open printer: %s\n", sharename));
2034 /* check for existing dst printer */
2035 if (!net_spoolss_getprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, level, &info_dst)) {
2036 printf ("could not get printer, creating printer.\n");
2037 } else {
2038 DEBUG(1,("printer already exists: %s\n", sharename));
2039 /* close printer handle here - dst only, not got src yet. */
2040 if (is_valid_policy_hnd(&hnd_dst)) {
2041 rpccli_spoolss_ClosePrinter(pipe_hnd_dst, mem_ctx, &hnd_dst, NULL);
2043 continue;
2046 /* now get again src printer ctr via getprinter,
2047 we first need a handle for that */
2049 /* open src printer handle */
2050 if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, sharename,
2051 MAXIMUM_ALLOWED_ACCESS, cli->user_name, &hnd_src))
2052 goto done;
2054 /* getprinter on the src server */
2055 if (!net_spoolss_getprinter(pipe_hnd, mem_ctx, &hnd_src, level, &info_src))
2056 goto done;
2058 /* copy each src printer to a dst printer 1:1,
2059 maybe some values have to be changed though */
2060 d_printf("creating printer: %s\n", printername);
2062 info_ctr.level = level;
2063 info_ctr.info.info2 = (struct spoolss_SetPrinterInfo2 *)&info_src.info2;
2065 result = rpccli_spoolss_addprinterex(pipe_hnd_dst,
2066 mem_ctx,
2067 &info_ctr);
2069 if (W_ERROR_IS_OK(result))
2070 d_printf ("printer [%s] successfully added.\n", printername);
2071 else if (W_ERROR_V(result) == W_ERROR_V(WERR_PRINTER_ALREADY_EXISTS))
2072 d_fprintf (stderr, "printer [%s] already exists.\n", printername);
2073 else {
2074 d_fprintf (stderr, "could not create printer [%s]\n", printername);
2075 goto done;
2078 /* close printer handles here */
2079 if (is_valid_policy_hnd(&hnd_src)) {
2080 rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd_src, NULL);
2083 if (is_valid_policy_hnd(&hnd_dst)) {
2084 rpccli_spoolss_ClosePrinter(pipe_hnd_dst, mem_ctx, &hnd_dst, NULL);
2088 nt_status = NT_STATUS_OK;
2090 done:
2091 if (is_valid_policy_hnd(&hnd_src))
2092 rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd_src, NULL);
2094 if (is_valid_policy_hnd(&hnd_dst))
2095 rpccli_spoolss_ClosePrinter(pipe_hnd_dst, mem_ctx, &hnd_dst, NULL);
2097 if (cli_dst) {
2098 cli_shutdown(cli_dst);
2100 return nt_status;
2104 * Migrate Printer-Settings from a src server to the dst server
2105 * (for this to work, printers and drivers already have to be migrated earlier)
2107 * All parameters are provided by the run_rpc_command function, except for
2108 * argc, argv which are passed through.
2110 * @param c A net_context structure
2111 * @param domain_sid The domain sid aquired from the remote server
2112 * @param cli A cli_state connected to the server.
2113 * @param mem_ctx Talloc context, destoyed on compleation of the function.
2114 * @param argc Standard main() style argc
2115 * @param argv Standard main() style argv. Initial components are already
2116 * stripped
2118 * @return Normal NTSTATUS return.
2121 NTSTATUS rpc_printer_migrate_settings_internals(struct net_context *c,
2122 const DOM_SID *domain_sid,
2123 const char *domain_name,
2124 struct cli_state *cli,
2125 struct rpc_pipe_client *pipe_hnd,
2126 TALLOC_CTX *mem_ctx,
2127 int argc,
2128 const char **argv)
2131 /* FIXME: Here the nightmare begins */
2133 WERROR result;
2134 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
2135 uint32_t i = 0, p = 0, j = 0;
2136 uint32_t num_printers;
2137 uint32_t level = 2;
2138 const char *printername, *sharename;
2139 struct rpc_pipe_client *pipe_hnd_dst = NULL;
2140 struct policy_handle hnd_src, hnd_dst;
2141 union spoolss_PrinterInfo *info_enum;
2142 union spoolss_PrinterInfo info_dst_publish;
2143 union spoolss_PrinterInfo info_dst;
2144 struct cli_state *cli_dst = NULL;
2145 char *devicename = NULL, *unc_name = NULL, *url = NULL;
2146 const char *longname;
2147 const char **keylist = NULL;
2149 /* FIXME GD */
2150 ZERO_STRUCT(info_dst_publish);
2152 DEBUG(3,("copying printer settings\n"));
2154 /* connect destination PI_SPOOLSS */
2155 nt_status = connect_dst_pipe(c, &cli_dst, &pipe_hnd_dst,
2156 &ndr_table_spoolss.syntax_id);
2157 if (!NT_STATUS_IS_OK(nt_status))
2158 return nt_status;
2160 /* enum src printers */
2161 if (!get_printer_info(pipe_hnd, mem_ctx, level, argc, argv, &num_printers, &info_enum)) {
2162 nt_status = NT_STATUS_UNSUCCESSFUL;
2163 goto done;
2166 if (!num_printers) {
2167 printf ("no printers found on server.\n");
2168 nt_status = NT_STATUS_OK;
2169 goto done;
2173 /* needed for dns-strings in regkeys */
2174 longname = get_mydnsfullname();
2175 if (!longname) {
2176 nt_status = NT_STATUS_UNSUCCESSFUL;
2177 goto done;
2180 /* do something for all printers */
2181 for (i = 0; i < num_printers; i++) {
2183 uint32_t value_offered = 0, value_needed;
2184 uint32_t data_offered = 0, data_needed;
2185 enum winreg_Type type;
2186 uint8_t *buffer = NULL;
2187 const char *value_name = NULL;
2189 /* do some initialization */
2190 printername = info_enum[i].info2.printername;
2191 sharename = info_enum[i].info2.sharename;
2193 if (!printername || !sharename) {
2194 nt_status = NT_STATUS_UNSUCCESSFUL;
2195 goto done;
2197 /* we can reset NT_STATUS here because we do not
2198 get any real NT_STATUS-codes anymore from now on */
2199 nt_status = NT_STATUS_UNSUCCESSFUL;
2201 d_printf("migrating printer settings for: [%s] / [%s]\n",
2202 printername, sharename);
2205 /* open src printer handle */
2206 if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, sharename,
2207 MAXIMUM_ALLOWED_ACCESS, cli->user_name, &hnd_src))
2208 goto done;
2210 /* open dst printer handle */
2211 if (!net_spoolss_open_printer_ex(pipe_hnd_dst, mem_ctx, sharename,
2212 PRINTER_ALL_ACCESS, cli_dst->user_name, &hnd_dst))
2213 goto done;
2215 /* check for existing dst printer */
2216 if (!net_spoolss_getprinter(pipe_hnd_dst, mem_ctx, &hnd_dst,
2217 level, &info_dst))
2218 goto done;
2221 /* STEP 1: COPY DEVICE-MODE and other
2222 PRINTER_INFO_2-attributes
2225 info_dst.info2 = info_enum[i].info2;
2227 /* why is the port always disconnected when the printer
2228 is correctly installed (incl. driver ???) */
2229 info_dst.info2.portname = SAMBA_PRINTER_PORT_NAME;
2231 /* check if printer is published */
2232 if (info_enum[i].info2.attributes & PRINTER_ATTRIBUTE_PUBLISHED) {
2234 /* check for existing dst printer */
2235 if (!net_spoolss_getprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, 7, &info_dst_publish))
2236 goto done;
2238 info_dst_publish.info7.action = DSPRINT_PUBLISH;
2240 /* ignore false from setprinter due to WERR_IO_PENDING */
2241 net_spoolss_setprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, 7, &info_dst_publish);
2243 DEBUG(3,("republished printer\n"));
2246 if (info_enum[i].info2.devmode != NULL) {
2248 /* copy devmode (info level 2) */
2249 info_dst.info2.devmode = info_enum[i].info2.devmode;
2251 /* do not copy security descriptor (we have another
2252 * command for that) */
2253 info_dst.info2.secdesc = NULL;
2255 #if 0
2256 info_dst.info2.devmode.devicename =
2257 talloc_asprintf(mem_ctx, "\\\\%s\\%s",
2258 longname, printername);
2259 if (!info_dst.info2.devmode.devicename) {
2260 nt_status = NT_STATUS_NO_MEMORY;
2261 goto done;
2263 #endif
2264 if (!net_spoolss_setprinter(pipe_hnd_dst, mem_ctx, &hnd_dst,
2265 level, &info_dst))
2266 goto done;
2268 DEBUGADD(1,("\tSetPrinter of DEVICEMODE succeeded\n"));
2271 /* STEP 2: COPY REGISTRY VALUES */
2273 /* please keep in mind that samba parse_spools gives horribly
2274 crippled results when used to rpccli_spoolss_enumprinterdataex
2275 a win2k3-server. (Bugzilla #1851)
2276 FIXME: IIRC I've seen it too on a win2k-server
2279 /* enumerate data on src handle */
2280 nt_status = rpccli_spoolss_EnumPrinterData(pipe_hnd, mem_ctx,
2281 &hnd_src,
2283 value_name,
2284 value_offered,
2285 &value_needed,
2286 &type,
2287 buffer,
2288 data_offered,
2289 &data_needed,
2290 &result);
2292 data_offered = data_needed;
2293 value_offered = value_needed;
2294 buffer = talloc_zero_array(mem_ctx, uint8_t, data_needed);
2295 value_name = talloc_zero_array(mem_ctx, char, value_needed);
2297 /* loop for all printerdata of "PrinterDriverData" */
2298 while (NT_STATUS_IS_OK(nt_status) && W_ERROR_IS_OK(result)) {
2300 nt_status = rpccli_spoolss_EnumPrinterData(pipe_hnd, mem_ctx,
2301 &hnd_src,
2302 p++,
2303 value_name,
2304 value_offered,
2305 &value_needed,
2306 &type,
2307 buffer,
2308 data_offered,
2309 &data_needed,
2310 &result);
2311 /* loop for all reg_keys */
2312 if (NT_STATUS_IS_OK(nt_status) && W_ERROR_IS_OK(result)) {
2314 REGISTRY_VALUE v;
2315 DATA_BLOB blob;
2316 union spoolss_PrinterData printer_data;
2318 /* display_value */
2319 if (c->opt_verbose) {
2320 fstrcpy(v.valuename, value_name);
2321 v.type = type;
2322 v.size = data_offered;
2323 v.data_p = buffer;
2324 display_reg_value(SPOOL_PRINTERDATA_KEY, v);
2327 result = pull_spoolss_PrinterData(mem_ctx,
2328 &blob,
2329 &printer_data,
2330 type);
2331 if (!W_ERROR_IS_OK(result)) {
2332 goto done;
2335 /* set_value */
2336 if (!net_spoolss_setprinterdata(pipe_hnd_dst, mem_ctx,
2337 &hnd_dst, value_name,
2338 type, printer_data))
2339 goto done;
2341 DEBUGADD(1,("\tSetPrinterData of [%s] succeeded\n",
2342 v.valuename));
2346 /* STEP 3: COPY SUBKEY VALUES */
2348 /* here we need to enum all printer_keys and then work
2349 on the result with enum_printer_key_ex. nt4 does not
2350 respond to enumprinterkey, win2k does, so continue
2351 in case of an error */
2353 if (!net_spoolss_enumprinterkey(pipe_hnd, mem_ctx, &hnd_src, "", &keylist)) {
2354 printf("got no key-data\n");
2355 continue;
2359 /* work on a list of printer keys
2360 each key has to be enumerated to get all required
2361 information. information is then set via setprinterdataex-calls */
2363 if (keylist == NULL)
2364 continue;
2366 for (i=0; keylist && keylist[i] != NULL; i++) {
2368 const char *subkey = keylist[i];
2369 uint32_t count;
2370 struct spoolss_PrinterEnumValues *info;
2372 /* enumerate all src subkeys */
2373 if (!net_spoolss_enumprinterdataex(pipe_hnd, mem_ctx, 0,
2374 &hnd_src, subkey,
2375 &count, &info)) {
2376 goto done;
2379 for (j=0; j < count; j++) {
2381 REGISTRY_VALUE value;
2382 UNISTR2 data;
2384 /* although samba replies with sane data in most cases we
2385 should try to avoid writing wrong registry data */
2387 if (strequal(info[j].value_name, SPOOL_REG_PORTNAME) ||
2388 strequal(info[j].value_name, SPOOL_REG_UNCNAME) ||
2389 strequal(info[j].value_name, SPOOL_REG_URL) ||
2390 strequal(info[j].value_name, SPOOL_REG_SHORTSERVERNAME) ||
2391 strequal(info[j].value_name, SPOOL_REG_SERVERNAME)) {
2393 if (strequal(info[j].value_name, SPOOL_REG_PORTNAME)) {
2395 /* although windows uses a multi-sz, we use a sz */
2396 init_unistr2(&data, SAMBA_PRINTER_PORT_NAME, UNI_STR_TERMINATE);
2397 fstrcpy(value.valuename, SPOOL_REG_PORTNAME);
2400 if (strequal(info[j].value_name, SPOOL_REG_UNCNAME)) {
2402 if (asprintf(&unc_name, "\\\\%s\\%s", longname, sharename) < 0) {
2403 nt_status = NT_STATUS_NO_MEMORY;
2404 goto done;
2406 init_unistr2(&data, unc_name, UNI_STR_TERMINATE);
2407 fstrcpy(value.valuename, SPOOL_REG_UNCNAME);
2410 if (strequal(info[j].value_name, SPOOL_REG_URL)) {
2412 continue;
2414 #if 0
2415 /* FIXME: should we really do that ??? */
2416 if (asprintf(&url, "http://%s:631/printers/%s", longname, sharename) < 0) {
2417 nt_status = NT_STATUS_NO_MEMORY;
2418 goto done;
2420 init_unistr2(&data, url, UNI_STR_TERMINATE);
2421 fstrcpy(value.valuename, SPOOL_REG_URL);
2422 #endif
2425 if (strequal(info[j].value_name, SPOOL_REG_SERVERNAME)) {
2427 init_unistr2(&data, longname, UNI_STR_TERMINATE);
2428 fstrcpy(value.valuename, SPOOL_REG_SERVERNAME);
2431 if (strequal(info[j].value_name, SPOOL_REG_SHORTSERVERNAME)) {
2433 init_unistr2(&data, global_myname(), UNI_STR_TERMINATE);
2434 fstrcpy(value.valuename, SPOOL_REG_SHORTSERVERNAME);
2437 value.type = REG_SZ;
2438 value.size = data.uni_str_len * 2;
2439 if (value.size) {
2440 value.data_p = (uint8_t *)TALLOC_MEMDUP(mem_ctx, data.buffer, value.size);
2441 } else {
2442 value.data_p = NULL;
2445 if (c->opt_verbose)
2446 display_reg_value(subkey, value);
2448 /* here we have to set all subkeys on the dst server */
2449 if (!net_spoolss_setprinterdataex(pipe_hnd_dst, mem_ctx, &hnd_dst,
2450 subkey, &value))
2451 goto done;
2453 } else {
2455 REGISTRY_VALUE v;
2456 DATA_BLOB blob;
2458 result = push_spoolss_PrinterData(mem_ctx, &blob,
2459 info[j].type,
2460 info[j].data);
2461 if (!W_ERROR_IS_OK(result)) {
2462 goto done;
2465 fstrcpy(v.valuename, info[j].value_name);
2466 v.type = info[j].type;
2467 v.data_p = blob.data;
2468 v.size = blob.length;
2470 if (c->opt_verbose) {
2471 display_reg_value(subkey, v);
2474 /* here we have to set all subkeys on the dst server */
2475 if (!net_spoolss_setprinterdataex(pipe_hnd_dst, mem_ctx, &hnd_dst,
2476 subkey, &v)) {
2477 goto done;
2482 DEBUGADD(1,("\tSetPrinterDataEx of key [%s\\%s] succeeded\n",
2483 subkey, info[j].value_name));
2488 TALLOC_FREE(keylist);
2490 /* close printer handles here */
2491 if (is_valid_policy_hnd(&hnd_src)) {
2492 rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd_src, NULL);
2495 if (is_valid_policy_hnd(&hnd_dst)) {
2496 rpccli_spoolss_ClosePrinter(pipe_hnd_dst, mem_ctx, &hnd_dst, NULL);
2501 nt_status = NT_STATUS_OK;
2503 done:
2504 SAFE_FREE(devicename);
2505 SAFE_FREE(url);
2506 SAFE_FREE(unc_name);
2508 if (is_valid_policy_hnd(&hnd_src))
2509 rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd_src, NULL);
2511 if (is_valid_policy_hnd(&hnd_dst))
2512 rpccli_spoolss_ClosePrinter(pipe_hnd_dst, mem_ctx, &hnd_dst, NULL);
2514 if (cli_dst) {
2515 cli_shutdown(cli_dst);
2517 return nt_status;