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/>.
20 #include "system/filesys.h"
21 #include "utils/net.h"
22 #include "rpc_client/rpc_client.h"
23 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
24 #include "rpc_client/cli_spoolss.h"
25 #include "rpc_client/init_spoolss.h"
26 #include "nt_printing.h"
27 #include "registry/reg_objects.h"
28 #include "../libcli/security/security.h"
29 #include "../libcli/registry/util_reg.h"
32 /* support itanium as well */
33 static const struct print_architecture_table_node archi_table[]= {
35 {"Windows 4.0", "WIN40", 0 },
36 {"Windows NT x86", "W32X86", 2 },
37 {"Windows NT x86", "W32X86", 3 },
38 {"Windows NT R4000", "W32MIPS", 2 },
39 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
40 {"Windows NT PowerPC", "W32PPC", 2 },
41 {"Windows IA64", "IA64", 3 },
42 {"Windows x64", "x64", 3 },
48 * This display-printdriver-functions was borrowed from rpcclient/cmd_spoolss.c.
49 * It is here for debugging purpose and should be removed later on.
52 /****************************************************************************
53 Printer info level 3 display function.
54 ****************************************************************************/
56 static void display_print_driver3(struct spoolss_DriverInfo3 *r)
64 printf(_("Printer Driver Info 3:\n"));
65 printf(_("\tVersion: [%x]\n"), r->version);
66 printf(_("\tDriver Name: [%s]\n"), r->driver_name);
67 printf(_("\tArchitecture: [%s]\n"), r->architecture);
68 printf(_("\tDriver Path: [%s]\n"), r->driver_path);
69 printf(_("\tDatafile: [%s]\n"), r->data_file);
70 printf(_("\tConfigfile: [%s]\n\n"), r->config_file);
71 printf(_("\tHelpfile: [%s]\n\n"), r->help_file);
73 for (i=0; r->dependent_files[i] != NULL; i++) {
74 printf(_("\tDependentfiles: [%s]\n"), r->dependent_files[i]);
79 printf(_("\tMonitorname: [%s]\n"), r->monitor_name);
80 printf(_("\tDefaultdatatype: [%s]\n\n"), r->default_datatype);
83 static void display_reg_value(const char *subkey, struct regval_blob *value)
88 switch(regval_type(value)) {
90 d_printf(_("\t[%s:%s]: REG_DWORD: 0x%08x\n"), subkey,
91 regval_name(value), *((uint32_t *) regval_data_p(value)));
95 blob = data_blob_const(regval_data_p(value), regval_size(value));
96 pull_reg_sz(talloc_tos(), &blob, &text);
100 d_printf(_("\t[%s:%s]: REG_SZ: %s\n"), subkey, regval_name(value),
105 d_printf(_("\t[%s:%s]: REG_BINARY: unknown length value not "
107 subkey, regval_name(value));
113 blob = data_blob_const(regval_data_p(value), regval_size(value));
115 if (!pull_reg_multi_sz(NULL, &blob, &values)) {
116 d_printf("pull_reg_multi_sz failed\n");
120 printf("%s: REG_MULTI_SZ: \n", regval_name(value));
121 for (i=0; values[i] != NULL; i++) {
122 d_printf("%s\n", values[i]);
129 d_printf(_("\t%s: unknown type %d\n"), regval_name(value),
136 * Copies ACLs, DOS-attributes and timestamps from one
137 * file or directory from one connected share to another connected share
139 * @param c A net_context structure
140 * @param mem_ctx A talloc-context
141 * @param cli_share_src A connected cli_state
142 * @param cli_share_dst A connected cli_state
143 * @param src_file The source file-name
144 * @param dst_file The destination file-name
145 * @param copy_acls Whether to copy acls
146 * @param copy_attrs Whether to copy DOS attributes
147 * @param copy_timestamps Whether to preserve timestamps
148 * @param is_file Whether this file is a file or a dir
150 * @return Normal NTSTATUS return.
153 NTSTATUS net_copy_fileattr(struct net_context *c,
155 struct cli_state *cli_share_src,
156 struct cli_state *cli_share_dst,
157 const char *src_name, const char *dst_name,
158 bool copy_acls, bool copy_attrs,
159 bool copy_timestamps, bool is_file)
161 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
162 uint16_t fnum_src = 0;
163 uint16_t fnum_dst = 0;
164 struct security_descriptor *sd = NULL;
166 time_t f_atime, f_ctime, f_mtime;
169 if (!copy_timestamps && !copy_acls && !copy_attrs)
172 /* open file/dir on the originating server */
174 DEBUGADD(3,("opening %s %s on originating server\n",
175 is_file?"file":"dir", src_name));
177 if (!NT_STATUS_IS_OK(cli_ntcreate(cli_share_src, src_name, 0, READ_CONTROL_ACCESS, 0,
178 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0x0, 0x0, &fnum_src))) {
179 DEBUGADD(0,("cannot open %s %s on originating server %s\n",
180 is_file?"file":"dir", src_name, cli_errstr(cli_share_src)));
181 nt_status = cli_nt_error(cli_share_src);
188 /* get the security descriptor */
189 sd = cli_query_secdesc(cli_share_src, fnum_src, mem_ctx);
191 DEBUG(0,("failed to get security descriptor: %s\n",
192 cli_errstr(cli_share_src)));
193 nt_status = cli_nt_error(cli_share_src);
197 if (c->opt_verbose && DEBUGLEVEL >= 3)
198 display_sec_desc(sd);
202 if (copy_attrs || copy_timestamps) {
204 /* get file attributes */
205 if (!NT_STATUS_IS_OK(cli_getattrE(cli_share_src, fnum_src, &attr, NULL,
206 &f_ctime, &f_atime, &f_mtime))) {
207 DEBUG(0,("failed to get file-attrs: %s\n",
208 cli_errstr(cli_share_src)));
209 nt_status = cli_nt_error(cli_share_src);
215 /* open the file/dir on the destination server */
217 if (!NT_STATUS_IS_OK(cli_ntcreate(cli_share_dst, dst_name, 0, WRITE_DAC_ACCESS | WRITE_OWNER_ACCESS, 0,
218 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0x0, 0x0, &fnum_dst))) {
219 DEBUG(0,("failed to open %s on the destination server: %s: %s\n",
220 is_file?"file":"dir", dst_name, cli_errstr(cli_share_dst)));
221 nt_status = cli_nt_error(cli_share_dst);
225 if (copy_timestamps) {
228 if (!NT_STATUS_IS_OK(cli_setattrE(cli_share_dst, fnum_dst, f_ctime, f_atime, f_mtime))) {
229 DEBUG(0,("failed to set file-attrs (timestamps): %s\n",
230 cli_errstr(cli_share_dst)));
231 nt_status = cli_nt_error(cli_share_dst);
240 status = cli_set_secdesc(cli_share_dst, fnum_dst, sd);
241 if (!NT_STATUS_IS_OK(status)) {
242 DEBUG(0, ("could not set secdesc on %s: %s\n",
243 dst_name, nt_errstr(status)));
252 if (!NT_STATUS_IS_OK(cli_setatr(cli_share_dst, dst_name, attr, 0))) {
253 DEBUG(0,("failed to set file-attrs: %s\n",
254 cli_errstr(cli_share_dst)));
255 nt_status = cli_nt_error(cli_share_dst);
263 if (!NT_STATUS_IS_OK(cli_close(cli_share_src, fnum_src))) {
265 _("could not close %s on originating server: %s\n"),
266 is_file?"file":"dir", cli_errstr(cli_share_src));
267 nt_status = cli_nt_error(cli_share_src);
271 if (!NT_STATUS_IS_OK(cli_close(cli_share_dst, fnum_dst))) {
273 _("could not close %s on destination server: %s\n"),
274 is_file?"file":"dir", cli_errstr(cli_share_dst));
275 nt_status = cli_nt_error(cli_share_dst);
280 nt_status = NT_STATUS_OK;
286 cli_close(cli_share_src, fnum_src);
289 cli_close(cli_share_dst, fnum_dst);
295 * Copy a file or directory from a connected share to another connected share
297 * @param c A net_context structure
298 * @param mem_ctx A talloc-context
299 * @param cli_share_src A connected cli_state
300 * @param cli_share_dst A connected cli_state
301 * @param src_file The source file-name
302 * @param dst_file The destination file-name
303 * @param copy_acls Whether to copy acls
304 * @param copy_attrs Whether to copy DOS attributes
305 * @param copy_timestamps Whether to preserve timestamps
306 * @param is_file Whether this file is a file or a dir
308 * @return Normal NTSTATUS return.
311 NTSTATUS net_copy_file(struct net_context *c,
313 struct cli_state *cli_share_src,
314 struct cli_state *cli_share_dst,
315 const char *src_name, const char *dst_name,
316 bool copy_acls, bool copy_attrs,
317 bool copy_timestamps, bool is_file)
319 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
320 uint16_t fnum_src = 0;
321 uint16_t fnum_dst = 0;
322 static int io_bufsize = 64512;
323 int read_size = io_bufsize;
328 if (!src_name || !dst_name)
331 if (cli_share_src == NULL || cli_share_dst == NULL)
334 /* open on the originating server */
335 DEBUGADD(3,("opening %s %s on originating server\n",
336 is_file ? "file":"dir", src_name));
338 nt_status = cli_open(cli_share_src, src_name, O_RDONLY, DENY_NONE, &fnum_src);
340 nt_status = cli_ntcreate(cli_share_src, src_name, 0, READ_CONTROL_ACCESS, 0,
341 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0x0, 0x0, &fnum_src);
343 if (!NT_STATUS_IS_OK(nt_status)) {
344 DEBUGADD(0,("cannot open %s %s on originating server %s\n",
345 is_file ? "file":"dir",
346 src_name, cli_errstr(cli_share_src)));
353 /* open file on the destination server */
354 DEBUGADD(3,("opening file %s on destination server\n", dst_name));
355 nt_status = cli_open(cli_share_dst, dst_name,
356 O_RDWR|O_CREAT|O_TRUNC, DENY_NONE, &fnum_dst);
358 if (!NT_STATUS_IS_OK(nt_status)) {
359 DEBUGADD(1,("cannot create file %s on destination server: %s\n",
360 dst_name, cli_errstr(cli_share_dst)));
364 /* allocate memory */
365 if (!(data = (char *)SMB_MALLOC(read_size))) {
366 d_fprintf(stderr, _("malloc fail for size %d\n"),
368 nt_status = NT_STATUS_NO_MEMORY;
375 if (c->opt_verbose) {
377 d_printf(_("copying [\\\\%s\\%s%s] => [\\\\%s\\%s%s] "
378 "%s ACLs and %s DOS Attributes %s\n"),
379 cli_share_src->desthost, cli_share_src->share, src_name,
380 cli_share_dst->desthost, cli_share_dst->share, dst_name,
381 copy_acls ? _("with") : _("without"),
382 copy_attrs ? _("with") : _("without"),
383 copy_timestamps ? _("(preserving timestamps)") : "" );
391 n = cli_read(cli_share_src, fnum_src, data, nread,
397 ret = cli_write(cli_share_dst, fnum_dst, 0, data,
401 d_fprintf(stderr, _("Error writing file: %s\n"),
402 cli_errstr(cli_share_dst));
403 nt_status = cli_nt_error(cli_share_dst);
411 if (!is_file && !NT_STATUS_IS_OK(cli_chkpath(cli_share_dst, dst_name))) {
414 DEBUGADD(3,("creating dir %s on the destination server\n",
417 if (!NT_STATUS_IS_OK(cli_mkdir(cli_share_dst, dst_name))) {
418 DEBUG(0,("cannot create directory %s: %s\n",
419 dst_name, cli_errstr(cli_share_dst)));
420 nt_status = NT_STATUS_NO_SUCH_FILE;
423 if (!NT_STATUS_IS_OK(cli_chkpath(cli_share_dst, dst_name))) {
425 _("cannot check for directory %s: %s\n"),
426 dst_name, cli_errstr(cli_share_dst));
433 if (!NT_STATUS_IS_OK(cli_close(cli_share_src, fnum_src))) {
435 _("could not close file on originating server: %s\n"),
436 cli_errstr(cli_share_src));
437 nt_status = cli_nt_error(cli_share_src);
441 if (is_file && !NT_STATUS_IS_OK(cli_close(cli_share_dst, fnum_dst))) {
443 _("could not close file on destination server: %s\n"),
444 cli_errstr(cli_share_dst));
445 nt_status = cli_nt_error(cli_share_dst);
449 /* possibly we have to copy some file-attributes / acls / sd */
450 nt_status = net_copy_fileattr(c, mem_ctx, cli_share_src, cli_share_dst,
451 src_name, dst_name, copy_acls,
452 copy_attrs, copy_timestamps, is_file);
453 if (!NT_STATUS_IS_OK(nt_status))
457 nt_status = NT_STATUS_OK;
463 cli_close(cli_share_src, fnum_src);
466 cli_close(cli_share_dst, fnum_dst);
474 * Copy a driverfile from on connected share to another connected share
475 * This silently assumes that a driver-file is picked up from
477 * \\src_server\print$\{arch}\{version}\file
481 * \\dst_server\print$\{arch}\file
483 * to be added via setdriver-calls later.
484 * @param c A net_context structure
485 * @param mem_ctx A talloc-context
486 * @param cli_share_src A cli_state connected to source print$-share
487 * @param cli_share_dst A cli_state connected to destination print$-share
488 * @param file The file-name to be copied
489 * @param short_archi The name of the driver-architecture (short form)
491 * @return Normal NTSTATUS return.
494 static NTSTATUS net_copy_driverfile(struct net_context *c,
496 struct cli_state *cli_share_src,
497 struct cli_state *cli_share_dst,
498 const char *file, const char *short_archi) {
503 char *version = NULL;
504 char *filename = NULL;
511 /* scroll through the file until we have the part
512 beyond archi_table.short_archi */
514 while (next_token_talloc(mem_ctx, &p, &tok, "\\")) {
515 if (strequal(tok, short_archi)) {
516 next_token_talloc(mem_ctx, &p, &version, "\\");
517 next_token_talloc(mem_ctx, &p, &filename, "\\");
521 if (version == NULL || filename == NULL) {
522 return NT_STATUS_UNSUCCESSFUL;
525 /* build source file name */
526 src_name = talloc_asprintf(mem_ctx, "\\%s\\%s\\%s",
527 short_archi, version, filename);
528 if (src_name == NULL) {
529 return NT_STATUS_NO_MEMORY;
532 /* create destination file name */
533 dst_name = talloc_asprintf(mem_ctx, "\\%s\\%s", short_archi, filename);
534 if (dst_name == NULL) {
535 return NT_STATUS_NO_MEMORY;
539 /* finally copy the file */
540 return net_copy_file(c, mem_ctx, cli_share_src, cli_share_dst,
541 src_name, dst_name, false, false, false, true);
545 * Check for existing Architecture directory on a given server
547 * @param cli_share A cli_state connected to a print$-share
548 * @param short_archi The Architecture for the print-driver
550 * @return Normal NTSTATUS return.
553 static NTSTATUS check_arch_dir(struct cli_state *cli_share, const char *short_archi)
556 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
559 if (asprintf(&dir, "\\%s", short_archi) < 0) {
560 return NT_STATUS_NO_MEMORY;
563 DEBUG(10,("creating print-driver dir for architecture: %s\n",
566 if (!NT_STATUS_IS_OK(cli_mkdir(cli_share, dir))) {
567 DEBUG(1,("cannot create directory %s: %s\n",
568 dir, cli_errstr(cli_share)));
569 nt_status = NT_STATUS_NO_SUCH_FILE;
572 if (!NT_STATUS_IS_OK(cli_chkpath(cli_share, dir))) {
573 d_fprintf(stderr, _("cannot check %s: %s\n"),
574 dir, cli_errstr(cli_share));
578 nt_status = NT_STATUS_OK;
586 * Copy a print-driver (level 3) from one connected print$-share to another
587 * connected print$-share
589 * @param c A net_context structure
590 * @param mem_ctx A talloc-context
591 * @param cli_share_src A cli_state connected to a print$-share
592 * @param cli_share_dst A cli_state connected to a print$-share
593 * @param short_archi The Architecture for the print-driver
594 * @param i1 The DRIVER_INFO_3-struct
596 * @return Normal NTSTATUS return.
599 static NTSTATUS copy_print_driver_3(struct net_context *c,
601 struct cli_state *cli_share_src,
602 struct cli_state *cli_share_dst,
603 const char *short_archi,
604 struct spoolss_DriverInfo3 *r)
606 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
614 d_printf(_("copying driver: [%s], for architecture: [%s], "
616 r->driver_name, short_archi, r->version);
618 nt_status = net_copy_driverfile(c, mem_ctx, cli_share_src, cli_share_dst,
619 r->driver_path, short_archi);
620 if (!NT_STATUS_IS_OK(nt_status))
623 nt_status = net_copy_driverfile(c, mem_ctx, cli_share_src, cli_share_dst,
624 r->data_file, short_archi);
625 if (!NT_STATUS_IS_OK(nt_status))
628 nt_status = net_copy_driverfile(c, mem_ctx, cli_share_src, cli_share_dst,
629 r->config_file, short_archi);
630 if (!NT_STATUS_IS_OK(nt_status))
633 nt_status = net_copy_driverfile(c, mem_ctx, cli_share_src, cli_share_dst,
634 r->help_file, short_archi);
635 if (!NT_STATUS_IS_OK(nt_status))
638 for (i=0; r->dependent_files[i] != NULL; i++) {
640 nt_status = net_copy_driverfile(c, mem_ctx,
641 cli_share_src, cli_share_dst,
642 r->dependent_files[i], short_archi);
643 if (!NT_STATUS_IS_OK(nt_status)) {
652 * net_spoolss-functions
653 * =====================
655 * the net_spoolss-functions aim to simplify spoolss-client-functions
656 * required during the migration-process wrt buffer-sizes, returned
659 * this greatly reduces the complexitiy of the migrate-functions.
663 static bool net_spoolss_enum_printers(struct rpc_pipe_client *pipe_hnd,
668 uint32_t *num_printers,
669 union spoolss_PrinterInfo **info)
675 result = rpccli_spoolss_enumprinters(pipe_hnd, mem_ctx,
682 if (!W_ERROR_IS_OK(result)) {
683 printf(_("cannot enum printers: %s\n"), win_errstr(result));
690 static bool net_spoolss_open_printer_ex(struct rpc_pipe_client *pipe_hnd,
692 const char *printername,
693 uint32_t access_required,
694 const char *username,
695 struct policy_handle *hnd)
698 fstring printername2;
700 fstrcpy(printername2, pipe_hnd->srv_name_slash);
701 fstrcat(printername2, "\\");
702 fstrcat(printername2, printername);
704 DEBUG(10,("connecting to: %s as %s for %s and access: %x\n",
705 pipe_hnd->srv_name_slash, username, printername2, access_required));
708 result = rpccli_spoolss_openprinter_ex(pipe_hnd, mem_ctx,
713 /* be more verbose */
714 if (W_ERROR_V(result) == W_ERROR_V(WERR_ACCESS_DENIED)) {
716 _("no access to printer [%s] on [%s] for user [%s] "
718 printername2, pipe_hnd->srv_name_slash, username);
722 if (!W_ERROR_IS_OK(result)) {
723 d_fprintf(stderr,_("cannot open printer %s on server %s: %s\n"),
724 printername2, pipe_hnd->srv_name_slash, win_errstr(result));
728 DEBUG(2,("got printer handle for printer: %s, server: %s\n",
729 printername2, pipe_hnd->srv_name_slash));
734 static bool net_spoolss_getprinter(struct rpc_pipe_client *pipe_hnd,
736 struct policy_handle *hnd,
738 union spoolss_PrinterInfo *info)
742 /* getprinter call */
743 result = rpccli_spoolss_getprinter(pipe_hnd, mem_ctx,
748 if (!W_ERROR_IS_OK(result)) {
749 printf(_("cannot get printer-info: %s\n"), win_errstr(result));
756 static bool net_spoolss_setprinter(struct rpc_pipe_client *pipe_hnd,
758 struct policy_handle *hnd,
760 union spoolss_PrinterInfo *info)
762 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
765 struct spoolss_SetPrinterInfoCtr info_ctr;
766 struct spoolss_SetPrinterInfo2 info2;
767 struct spoolss_DevmodeContainer devmode_ctr;
768 struct sec_desc_buf secdesc_ctr;
770 ZERO_STRUCT(devmode_ctr);
771 ZERO_STRUCT(secdesc_ctr);
773 /* setprinter call */
775 info_ctr.level = level;
778 info_ctr.info.info0 = (struct spoolss_SetPrinterInfo0 *)
779 (void *)&info->info0;
782 info_ctr.info.info1 = (struct spoolss_SetPrinterInfo1 *)
783 (void *)&info->info1;
786 spoolss_printerinfo2_to_setprinterinfo2(&info->info2, &info2);
787 info_ctr.info.info2 = &info2;
790 info_ctr.info.info3 = (struct spoolss_SetPrinterInfo3 *)
791 (void *)&info->info3;
794 info_ctr.info.info4 = (struct spoolss_SetPrinterInfo4 *)
795 (void *)&info->info4;
798 info_ctr.info.info5 = (struct spoolss_SetPrinterInfo5 *)
799 (void *)&info->info5;
802 info_ctr.info.info6 = (struct spoolss_SetPrinterInfo6 *)
803 (void *)&info->info6;
806 info_ctr.info.info7 = (struct spoolss_SetPrinterInfo7 *)
807 (void *)&info->info7;
811 info_ctr.info.info8 = (struct spoolss_SetPrinterInfo8 *)
812 (void *)&info->info8;
815 info_ctr.info.info9 = (struct spoolss_SetPrinterInfo9 *)
816 (void *)&info->info9;
823 status = dcerpc_spoolss_SetPrinter(b, mem_ctx,
830 if (!NT_STATUS_IS_OK(status)) {
831 printf(_("cannot set printer-info: %s\n"), nt_errstr(status));
834 if (!W_ERROR_IS_OK(result)) {
835 printf(_("cannot set printer-info: %s\n"), win_errstr(result));
843 static bool net_spoolss_setprinterdata(struct rpc_pipe_client *pipe_hnd,
845 struct policy_handle *hnd,
846 const char *value_name,
847 enum winreg_Type type,
851 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
855 /* setprinterdata call */
856 status = dcerpc_spoolss_SetPrinterData(b, mem_ctx,
863 if (!NT_STATUS_IS_OK(status)) {
864 printf (_("unable to set printerdata: %s\n"),
868 if (!W_ERROR_IS_OK(result)) {
869 printf (_("unable to set printerdata: %s\n"),
878 static bool net_spoolss_enumprinterkey(struct rpc_pipe_client *pipe_hnd,
880 struct policy_handle *hnd,
882 const char ***keylist)
886 /* enumprinterkey call */
887 result = rpccli_spoolss_enumprinterkey(pipe_hnd, mem_ctx, hnd, keyname, keylist, 0);
889 if (!W_ERROR_IS_OK(result)) {
890 printf(_("enumprinterkey failed: %s\n"), win_errstr(result));
897 static bool net_spoolss_enumprinterdataex(struct rpc_pipe_client *pipe_hnd,
900 struct policy_handle *hnd,
903 struct spoolss_PrinterEnumValues **info)
907 /* enumprinterdataex call */
908 result = rpccli_spoolss_enumprinterdataex(pipe_hnd, mem_ctx,
915 if (!W_ERROR_IS_OK(result)) {
916 printf(_("enumprinterdataex failed: %s\n"), win_errstr(result));
924 static bool net_spoolss_setprinterdataex(struct rpc_pipe_client *pipe_hnd,
926 struct policy_handle *hnd,
928 struct regval_blob *value)
930 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
934 /* setprinterdataex call */
935 status = dcerpc_spoolss_SetPrinterDataEx(b, mem_ctx,
940 regval_data_p(value),
943 if (!NT_STATUS_IS_OK(status)) {
944 printf(_("could not set printerdataex: %s\n"),
948 if (!W_ERROR_IS_OK(result)) {
949 printf(_("could not set printerdataex: %s\n"),
957 static bool net_spoolss_enumforms(struct rpc_pipe_client *pipe_hnd,
959 struct policy_handle *hnd,
962 union spoolss_FormInfo **forms)
967 result = rpccli_spoolss_enumforms(pipe_hnd, mem_ctx,
973 if (!W_ERROR_IS_OK(result)) {
974 printf(_("could not enum forms: %s\n"), win_errstr(result));
981 static bool net_spoolss_enumprinterdrivers (struct rpc_pipe_client *pipe_hnd,
983 uint32_t level, const char *env,
985 union spoolss_DriverInfo **info)
989 /* enumprinterdrivers call */
990 result = rpccli_spoolss_enumprinterdrivers(pipe_hnd, mem_ctx,
991 pipe_hnd->srv_name_slash,
997 if (!W_ERROR_IS_OK(result)) {
998 if (W_ERROR_V(result) != W_ERROR_V(WERR_INVALID_ENVIRONMENT)) {
999 printf(_("cannot enum drivers for environment %s: %s\n"), env,
1000 win_errstr(result));
1003 printf(_("Server does not support environment [%s]\n"),
1011 static bool net_spoolss_getprinterdriver(struct rpc_pipe_client *pipe_hnd,
1012 TALLOC_CTX *mem_ctx,
1013 struct policy_handle *hnd, uint32_t level,
1014 const char *env, int version,
1015 union spoolss_DriverInfo *info)
1018 uint32_t server_major_version;
1019 uint32_t server_minor_version;
1021 /* getprinterdriver call */
1022 result = rpccli_spoolss_getprinterdriver2(pipe_hnd, mem_ctx,
1030 &server_major_version,
1031 &server_minor_version);
1032 if (!W_ERROR_IS_OK(result)) {
1033 DEBUG(1,("cannot get driver (for architecture: %s): %s\n",
1034 env, win_errstr(result)));
1035 if (W_ERROR_V(result) != W_ERROR_V(WERR_UNKNOWN_PRINTER_DRIVER) &&
1036 W_ERROR_V(result) != W_ERROR_V(WERR_INVALID_ENVIRONMENT)) {
1037 printf(_("cannot get driver: %s\n"),
1038 win_errstr(result));
1047 static bool net_spoolss_addprinterdriver(struct rpc_pipe_client *pipe_hnd,
1048 TALLOC_CTX *mem_ctx, uint32_t level,
1049 union spoolss_DriverInfo *info)
1051 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
1054 struct spoolss_AddDriverInfoCtr info_ctr;
1056 info_ctr.level = level;
1060 info_ctr.info.info2 = (struct spoolss_AddDriverInfo2 *)
1061 (void *)&info->info2;
1064 info_ctr.info.info3 = (struct spoolss_AddDriverInfo3 *)
1065 (void *)&info->info3;
1068 printf(_("unsupported info level: %d\n"), level);
1072 /* addprinterdriver call */
1073 status = dcerpc_spoolss_AddPrinterDriver(b, mem_ctx,
1074 pipe_hnd->srv_name_slash,
1077 if (!NT_STATUS_IS_OK(status)) {
1078 printf(_("cannot add driver: %s\n"), nt_errstr(status));
1081 /* be more verbose */
1082 if (W_ERROR_V(result) == W_ERROR_V(WERR_ACCESS_DENIED)) {
1083 printf(_("You are not allowed to add drivers\n"));
1086 if (!W_ERROR_IS_OK(result)) {
1087 printf(_("cannot add driver: %s\n"), win_errstr(result));
1095 * abstraction function to get uint32_t num_printers and PRINTER_INFO_CTR ctr
1096 * for a single printer or for all printers depending on argc/argv
1099 static bool get_printer_info(struct rpc_pipe_client *pipe_hnd,
1100 TALLOC_CTX *mem_ctx,
1104 uint32_t *num_printers,
1105 union spoolss_PrinterInfo **info_p)
1107 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
1108 struct policy_handle hnd;
1111 /* no arguments given, enumerate all printers */
1114 if (!net_spoolss_enum_printers(pipe_hnd, mem_ctx, NULL,
1115 PRINTER_ENUM_LOCAL|PRINTER_ENUM_SHARED,
1116 level, num_printers, info_p))
1122 /* argument given, get a single printer by name */
1123 if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, argv[0],
1124 MAXIMUM_ALLOWED_ACCESS,
1125 pipe_hnd->auth->user_name,
1129 *info_p = talloc_zero(mem_ctx, union spoolss_PrinterInfo);
1130 if (*info_p == NULL) {
1134 if (!net_spoolss_getprinter(pipe_hnd, mem_ctx, &hnd, level, *info_p)) {
1135 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &werr);
1139 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &werr);
1144 DEBUG(3,("got %d printers\n", *num_printers));
1151 * List print-queues (including local printers that are not shared)
1153 * All parameters are provided by the run_rpc_command function, except for
1154 * argc, argv which are passed through.
1156 * @param c A net_context structure
1157 * @param domain_sid The domain sid aquired from the remote server
1158 * @param cli A cli_state connected to the server.
1159 * @param mem_ctx Talloc context, destoyed on compleation of the function.
1160 * @param argc Standard main() style argc
1161 * @param argv Standard main() style argv. Initial components are already
1164 * @return Normal NTSTATUS return.
1167 NTSTATUS rpc_printer_list_internals(struct net_context *c,
1168 const struct dom_sid *domain_sid,
1169 const char *domain_name,
1170 struct cli_state *cli,
1171 struct rpc_pipe_client *pipe_hnd,
1172 TALLOC_CTX *mem_ctx,
1176 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1177 uint32_t i, num_printers;
1179 const char *printername, *sharename;
1180 union spoolss_PrinterInfo *info;
1182 printf("listing printers\n");
1184 if (!get_printer_info(pipe_hnd, mem_ctx, level, argc, argv, &num_printers, &info))
1187 for (i = 0; i < num_printers; i++) {
1189 /* do some initialization */
1190 printername = info[i].info2.printername;
1191 sharename = info[i].info2.sharename;
1193 if (printername && sharename) {
1194 d_printf(_("printer %d: %s, shared as: %s\n"),
1195 i+1, printername, sharename);
1199 return NT_STATUS_OK;
1203 * List printer-drivers from a server
1205 * All parameters are provided by the run_rpc_command function, except for
1206 * argc, argv which are passed through.
1208 * @param c A net_context structure
1209 * @param domain_sid The domain sid aquired from the remote server
1210 * @param cli A cli_state connected to the server.
1211 * @param mem_ctx Talloc context, destoyed on compleation of the function.
1212 * @param argc Standard main() style argc
1213 * @param argv Standard main() style argv. Initial components are already
1216 * @return Normal NTSTATUS return.
1219 NTSTATUS rpc_printer_driver_list_internals(struct net_context *c,
1220 const struct dom_sid *domain_sid,
1221 const char *domain_name,
1222 struct cli_state *cli,
1223 struct rpc_pipe_client *pipe_hnd,
1224 TALLOC_CTX *mem_ctx,
1228 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1231 union spoolss_DriverInfo *info;
1234 printf(_("listing printer-drivers\n"));
1236 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1238 uint32_t num_drivers;
1240 /* enum remote drivers */
1241 if (!net_spoolss_enumprinterdrivers(pipe_hnd, mem_ctx, level,
1242 archi_table[i].long_archi,
1243 &num_drivers, &info)) {
1244 nt_status = NT_STATUS_UNSUCCESSFUL;
1248 if (num_drivers == 0) {
1249 d_printf(_("no drivers found on server for "
1250 "architecture: [%s].\n"),
1251 archi_table[i].long_archi);
1255 d_printf(_("got %d printer-drivers for architecture: [%s]\n"),
1256 num_drivers, archi_table[i].long_archi);
1259 /* do something for all drivers for architecture */
1260 for (d = 0; d < num_drivers; d++) {
1261 display_print_driver3(&info[d].info3);
1265 nt_status = NT_STATUS_OK;
1273 * Publish print-queues with args-wrapper
1275 * @param cli A cli_state connected to the server.
1276 * @param mem_ctx Talloc context, destoyed on compleation of the function.
1277 * @param argc Standard main() style argc
1278 * @param argv Standard main() style argv. Initial components are already
1282 * @return Normal NTSTATUS return.
1285 static NTSTATUS rpc_printer_publish_internals_args(struct rpc_pipe_client *pipe_hnd,
1286 TALLOC_CTX *mem_ctx,
1291 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
1292 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1293 uint32_t i, num_printers;
1295 const char *printername, *sharename;
1296 union spoolss_PrinterInfo *info_enum;
1297 union spoolss_PrinterInfo info;
1298 struct spoolss_SetPrinterInfoCtr info_ctr;
1299 struct spoolss_DevmodeContainer devmode_ctr;
1300 struct sec_desc_buf secdesc_ctr;
1301 struct policy_handle hnd;
1303 const char *action_str;
1305 if (!get_printer_info(pipe_hnd, mem_ctx, 2, argc, argv, &num_printers, &info_enum))
1308 for (i = 0; i < num_printers; i++) {
1310 /* do some initialization */
1311 printername = info_enum[i].info2.printername;
1312 sharename = info_enum[i].info2.sharename;
1313 if (!printername || !sharename) {
1317 /* open printer handle */
1318 if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, sharename,
1319 PRINTER_ALL_ACCESS, pipe_hnd->auth->user_name, &hnd))
1322 /* check for existing dst printer */
1323 if (!net_spoolss_getprinter(pipe_hnd, mem_ctx, &hnd, level, &info))
1326 /* check action and set string */
1328 case DSPRINT_PUBLISH:
1329 action_str = N_("published");
1331 case DSPRINT_UPDATE:
1332 action_str = N_("updated");
1334 case DSPRINT_UNPUBLISH:
1335 action_str = N_("unpublished");
1338 action_str = N_("unknown action");
1339 printf(_("unknown action: %d\n"), action);
1343 info.info7.action = action;
1345 info_ctr.info.info7 = (struct spoolss_SetPrinterInfo7 *)
1346 (void *)&info.info7;
1348 ZERO_STRUCT(devmode_ctr);
1349 ZERO_STRUCT(secdesc_ctr);
1351 nt_status = dcerpc_spoolss_SetPrinter(b, mem_ctx,
1358 if (!NT_STATUS_IS_OK(nt_status)) {
1359 printf(_("cannot set printer-info: %s\n"),
1360 nt_errstr(nt_status));
1363 if (!W_ERROR_IS_OK(result) && !W_ERROR_EQUAL(result, WERR_IO_PENDING)) {
1364 if ((action == DSPRINT_UPDATE) && W_ERROR_EQUAL(result, W_ERROR(0x80070002))) {
1365 printf(_("printer not published yet\n"));
1367 printf(_("cannot set printer-info: %s\n"),
1368 win_errstr(result));
1370 nt_status = werror_to_ntstatus(result);
1374 printf(_("successfully %s printer %s in Active Directory\n"),
1375 action_str, sharename);
1378 nt_status = NT_STATUS_OK;
1381 if (is_valid_policy_hnd(&hnd)) {
1382 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &result);
1388 NTSTATUS rpc_printer_publish_publish_internals(struct net_context *c,
1389 const struct dom_sid *domain_sid,
1390 const char *domain_name,
1391 struct cli_state *cli,
1392 struct rpc_pipe_client *pipe_hnd,
1393 TALLOC_CTX *mem_ctx,
1397 return rpc_printer_publish_internals_args(pipe_hnd, mem_ctx, argc, argv, DSPRINT_PUBLISH);
1400 NTSTATUS rpc_printer_publish_unpublish_internals(struct net_context *c,
1401 const struct dom_sid *domain_sid,
1402 const char *domain_name,
1403 struct cli_state *cli,
1404 struct rpc_pipe_client *pipe_hnd,
1405 TALLOC_CTX *mem_ctx,
1409 return rpc_printer_publish_internals_args(pipe_hnd, mem_ctx, argc, argv, DSPRINT_UNPUBLISH);
1412 NTSTATUS rpc_printer_publish_update_internals(struct net_context *c,
1413 const struct dom_sid *domain_sid,
1414 const char *domain_name,
1415 struct cli_state *cli,
1416 struct rpc_pipe_client *pipe_hnd,
1417 TALLOC_CTX *mem_ctx,
1421 return rpc_printer_publish_internals_args(pipe_hnd, mem_ctx, argc, argv, DSPRINT_UPDATE);
1425 * List print-queues w.r.t. their publishing state
1427 * All parameters are provided by the run_rpc_command function, except for
1428 * argc, argv which are passed through.
1430 * @param c A net_context structure
1431 * @param domain_sid The domain sid aquired from the remote server
1432 * @param cli A cli_state connected to the server.
1433 * @param mem_ctx Talloc context, destoyed on compleation of the function.
1434 * @param argc Standard main() style argc
1435 * @param argv Standard main() style argv. Initial components are already
1438 * @return Normal NTSTATUS return.
1441 NTSTATUS rpc_printer_publish_list_internals(struct net_context *c,
1442 const struct dom_sid *domain_sid,
1443 const char *domain_name,
1444 struct cli_state *cli,
1445 struct rpc_pipe_client *pipe_hnd,
1446 TALLOC_CTX *mem_ctx,
1450 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
1451 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1452 uint32_t i, num_printers;
1454 const char *printername, *sharename;
1455 union spoolss_PrinterInfo *info_enum;
1456 union spoolss_PrinterInfo info;
1457 struct policy_handle hnd;
1461 if (!get_printer_info(pipe_hnd, mem_ctx, 2, argc, argv, &num_printers, &info_enum))
1464 for (i = 0; i < num_printers; i++) {
1466 /* do some initialization */
1467 printername = info_enum[i].info2.printername;
1468 sharename = info_enum[i].info2.sharename;
1470 if (!printername || !sharename) {
1474 /* open printer handle */
1475 if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, sharename,
1476 PRINTER_ALL_ACCESS, cli->user_name, &hnd))
1479 /* check for existing dst printer */
1480 if (!net_spoolss_getprinter(pipe_hnd, mem_ctx, &hnd, level, &info))
1483 if (!info.info7.guid) {
1486 state = info.info7.action;
1488 case DSPRINT_PUBLISH:
1489 printf(_("printer [%s] is published"),
1492 printf(_(", guid: %s"),info.info7.guid);
1495 case DSPRINT_UNPUBLISH:
1496 printf(_("printer [%s] is unpublished\n"),
1499 case DSPRINT_UPDATE:
1500 printf(_("printer [%s] is currently updating\n"),
1504 printf(_("unknown state: %d\n"), state);
1509 nt_status = NT_STATUS_OK;
1512 if (is_valid_policy_hnd(&hnd)) {
1513 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &werr);
1520 * Migrate Printer-ACLs from a source server to the destination server
1522 * All parameters are provided by the run_rpc_command function, except for
1523 * argc, argv which are passed through.
1525 * @param c A net_context structure
1526 * @param domain_sid The domain sid aquired from the remote server
1527 * @param cli A cli_state connected to the server.
1528 * @param mem_ctx Talloc context, destoyed on compleation of the function.
1529 * @param argc Standard main() style argc
1530 * @param argv Standard main() style argv. Initial components are already
1533 * @return Normal NTSTATUS return.
1536 NTSTATUS rpc_printer_migrate_security_internals(struct net_context *c,
1537 const struct dom_sid *domain_sid,
1538 const char *domain_name,
1539 struct cli_state *cli,
1540 struct rpc_pipe_client *pipe_hnd,
1541 TALLOC_CTX *mem_ctx,
1545 struct dcerpc_binding_handle *b_src = pipe_hnd->binding_handle;
1546 /* TODO: what now, info2 or info3 ?
1547 convince jerry that we should add clientside setacls level 3 at least
1549 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1551 uint32_t num_printers;
1553 const char *printername, *sharename;
1554 struct rpc_pipe_client *pipe_hnd_dst = NULL;
1555 struct dcerpc_binding_handle *b_dst = NULL;
1556 struct policy_handle hnd_src, hnd_dst;
1557 union spoolss_PrinterInfo *info_enum;
1558 struct cli_state *cli_dst = NULL;
1559 union spoolss_PrinterInfo info_src, info_dst;
1562 DEBUG(3,("copying printer ACLs\n"));
1564 /* connect destination PI_SPOOLSS */
1565 nt_status = connect_dst_pipe(c, &cli_dst, &pipe_hnd_dst,
1566 &ndr_table_spoolss.syntax_id);
1567 if (!NT_STATUS_IS_OK(nt_status)) {
1570 b_dst = pipe_hnd_dst->binding_handle;
1572 /* enum source printers */
1573 if (!get_printer_info(pipe_hnd, mem_ctx, level, argc, argv, &num_printers, &info_enum)) {
1574 nt_status = NT_STATUS_UNSUCCESSFUL;
1578 if (!num_printers) {
1579 printf (_("no printers found on server.\n"));
1580 nt_status = NT_STATUS_OK;
1584 /* do something for all printers */
1585 for (i = 0; i < num_printers; i++) {
1587 /* do some initialization */
1588 printername = info_enum[i].info2.printername;
1589 sharename = info_enum[i].info2.sharename;
1591 if (!printername || !sharename) {
1592 nt_status = NT_STATUS_UNSUCCESSFUL;
1596 /* we can reset NT_STATUS here because we do not
1597 get any real NT_STATUS-codes anymore from now on */
1598 nt_status = NT_STATUS_UNSUCCESSFUL;
1600 d_printf(_("migrating printer ACLs for: [%s] / [%s]\n"),
1601 printername, sharename);
1603 /* according to msdn you have specify these access-rights
1604 to see the security descriptor
1605 - READ_CONTROL (DACL)
1606 - ACCESS_SYSTEM_SECURITY (SACL)
1609 /* open src printer handle */
1610 if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, sharename,
1611 MAXIMUM_ALLOWED_ACCESS, cli->user_name, &hnd_src))
1614 /* open dst printer handle */
1615 if (!net_spoolss_open_printer_ex(pipe_hnd_dst, mem_ctx, sharename,
1616 PRINTER_ALL_ACCESS, cli_dst->user_name, &hnd_dst))
1619 /* check for existing dst printer */
1620 if (!net_spoolss_getprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, level, &info_dst))
1623 /* check for existing src printer */
1624 if (!net_spoolss_getprinter(pipe_hnd, mem_ctx, &hnd_src, 3, &info_src))
1627 /* Copy Security Descriptor */
1629 /* copy secdesc (info level 2) */
1630 info_dst.info2.devmode = NULL;
1631 info_dst.info2.secdesc = dup_sec_desc(mem_ctx, info_src.info3.secdesc);
1634 display_sec_desc(info_dst.info2.secdesc);
1636 if (!net_spoolss_setprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, 2, &info_dst))
1639 DEBUGADD(1,("\tSetPrinter of SECDESC succeeded\n"));
1642 /* close printer handles here */
1643 if (is_valid_policy_hnd(&hnd_src)) {
1644 dcerpc_spoolss_ClosePrinter(b_src, mem_ctx, &hnd_src, &werr);
1647 if (is_valid_policy_hnd(&hnd_dst)) {
1648 dcerpc_spoolss_ClosePrinter(b_dst, mem_ctx, &hnd_dst, &werr);
1653 nt_status = NT_STATUS_OK;
1657 if (is_valid_policy_hnd(&hnd_src)) {
1658 dcerpc_spoolss_ClosePrinter(b_src, mem_ctx, &hnd_src, &werr);
1661 if (is_valid_policy_hnd(&hnd_dst)) {
1662 dcerpc_spoolss_ClosePrinter(b_dst, mem_ctx, &hnd_dst, &werr);
1666 cli_shutdown(cli_dst);
1672 * Migrate printer-forms from a src server to the dst server
1674 * All parameters are provided by the run_rpc_command function, except for
1675 * argc, argv which are passed through.
1677 * @param c A net_context structure
1678 * @param domain_sid The domain sid aquired from the remote server
1679 * @param cli A cli_state connected to the server.
1680 * @param mem_ctx Talloc context, destoyed on compleation of the function.
1681 * @param argc Standard main() style argc
1682 * @param argv Standard main() style argv. Initial components are already
1685 * @return Normal NTSTATUS return.
1688 NTSTATUS rpc_printer_migrate_forms_internals(struct net_context *c,
1689 const struct dom_sid *domain_sid,
1690 const char *domain_name,
1691 struct cli_state *cli,
1692 struct rpc_pipe_client *pipe_hnd,
1693 TALLOC_CTX *mem_ctx,
1697 struct dcerpc_binding_handle *b_src = pipe_hnd->binding_handle;
1698 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1701 uint32_t num_printers;
1703 const char *printername, *sharename;
1704 struct rpc_pipe_client *pipe_hnd_dst = NULL;
1705 struct dcerpc_binding_handle *b_dst = NULL;
1706 struct policy_handle hnd_src, hnd_dst;
1707 union spoolss_PrinterInfo *info_enum;
1708 union spoolss_PrinterInfo info_dst;
1710 union spoolss_FormInfo *forms;
1711 struct cli_state *cli_dst = NULL;
1713 DEBUG(3,("copying forms\n"));
1715 /* connect destination PI_SPOOLSS */
1716 nt_status = connect_dst_pipe(c, &cli_dst, &pipe_hnd_dst,
1717 &ndr_table_spoolss.syntax_id);
1718 if (!NT_STATUS_IS_OK(nt_status)) {
1721 b_dst = pipe_hnd_dst->binding_handle;
1723 /* enum src printers */
1724 if (!get_printer_info(pipe_hnd, mem_ctx, 2, argc, argv, &num_printers, &info_enum)) {
1725 nt_status = NT_STATUS_UNSUCCESSFUL;
1729 if (!num_printers) {
1730 printf (_("no printers found on server.\n"));
1731 nt_status = NT_STATUS_OK;
1735 /* do something for all printers */
1736 for (i = 0; i < num_printers; i++) {
1738 /* do some initialization */
1739 printername = info_enum[i].info2.printername;
1740 sharename = info_enum[i].info2.sharename;
1742 if (!printername || !sharename) {
1743 nt_status = NT_STATUS_UNSUCCESSFUL;
1746 /* we can reset NT_STATUS here because we do not
1747 get any real NT_STATUS-codes anymore from now on */
1748 nt_status = NT_STATUS_UNSUCCESSFUL;
1750 d_printf(_("migrating printer forms for: [%s] / [%s]\n"),
1751 printername, sharename);
1754 /* open src printer handle */
1755 if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, sharename,
1756 MAXIMUM_ALLOWED_ACCESS, cli->user_name, &hnd_src))
1759 /* open dst printer handle */
1760 if (!net_spoolss_open_printer_ex(pipe_hnd_dst, mem_ctx, sharename,
1761 PRINTER_ALL_ACCESS, cli->user_name, &hnd_dst))
1764 /* check for existing dst printer */
1765 if (!net_spoolss_getprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, level, &info_dst))
1768 /* finally migrate forms */
1769 if (!net_spoolss_enumforms(pipe_hnd, mem_ctx, &hnd_src, level, &num_forms, &forms))
1772 DEBUG(1,("got %d forms for printer\n", num_forms));
1775 for (f = 0; f < num_forms; f++) {
1777 union spoolss_AddFormInfo info;
1780 /* only migrate FORM_PRINTER types, according to jerry
1781 FORM_BUILTIN-types are hard-coded in samba */
1782 if (forms[f].info1.flags != SPOOLSS_FORM_PRINTER)
1786 d_printf(_("\tmigrating form # %d [%s] of type "
1788 f, forms[f].info1.form_name,
1789 forms[f].info1.flags);
1791 info.info1 = (struct spoolss_AddFormInfo1 *)
1792 (void *)&forms[f].info1;
1794 /* FIXME: there might be something wrong with samba's
1796 status = dcerpc_spoolss_AddForm(b_dst, mem_ctx,
1801 if (!NT_STATUS_IS_OK(status)) {
1802 d_printf(_("\tdcerpc_spoolss_AddForm form %d: [%s] - %s\n"),
1803 f, forms[f].info1.form_name, nt_errstr(status));
1806 if (!W_ERROR_IS_OK(result)) {
1807 d_printf(_("\tAddForm form %d: [%s] refused.\n"),
1808 f, forms[f].info1.form_name);
1812 DEBUGADD(1,("\tAddForm of [%s] succeeded\n",
1813 forms[f].info1.form_name));
1817 /* close printer handles here */
1818 if (is_valid_policy_hnd(&hnd_src)) {
1819 dcerpc_spoolss_ClosePrinter(b_src, mem_ctx, &hnd_src, &result);
1822 if (is_valid_policy_hnd(&hnd_dst)) {
1823 dcerpc_spoolss_ClosePrinter(b_dst, mem_ctx, &hnd_dst, &result);
1827 nt_status = NT_STATUS_OK;
1831 if (is_valid_policy_hnd(&hnd_src)) {
1832 dcerpc_spoolss_ClosePrinter(b_src, mem_ctx, &hnd_src, &result);
1835 if (is_valid_policy_hnd(&hnd_dst)) {
1836 dcerpc_spoolss_ClosePrinter(b_dst, mem_ctx, &hnd_dst, &result);
1840 cli_shutdown(cli_dst);
1846 * Migrate printer-drivers from a src server to the dst server
1848 * All parameters are provided by the run_rpc_command function, except for
1849 * argc, argv which are passed through.
1851 * @param c A net_context structure
1852 * @param domain_sid The domain sid aquired from the remote server
1853 * @param cli A cli_state connected to the server.
1854 * @param mem_ctx Talloc context, destoyed on compleation of the function.
1855 * @param argc Standard main() style argc
1856 * @param argv Standard main() style argv. Initial components are already
1859 * @return Normal NTSTATUS return.
1862 NTSTATUS rpc_printer_migrate_drivers_internals(struct net_context *c,
1863 const struct dom_sid *domain_sid,
1864 const char *domain_name,
1865 struct cli_state *cli,
1866 struct rpc_pipe_client *pipe_hnd,
1867 TALLOC_CTX *mem_ctx,
1871 struct dcerpc_binding_handle *b_src = pipe_hnd->binding_handle;
1872 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1874 uint32_t num_printers;
1876 const char *printername, *sharename;
1877 bool got_src_driver_share = false;
1878 bool got_dst_driver_share = false;
1879 struct rpc_pipe_client *pipe_hnd_dst = NULL;
1880 struct dcerpc_binding_handle *b_dst = NULL;
1881 struct policy_handle hnd_src, hnd_dst;
1882 union spoolss_DriverInfo drv_info_src;
1883 union spoolss_PrinterInfo *info_enum;
1884 union spoolss_PrinterInfo info_dst;
1885 struct cli_state *cli_dst = NULL;
1886 struct cli_state *cli_share_src = NULL;
1887 struct cli_state *cli_share_dst = NULL;
1888 const char *drivername = NULL;
1891 DEBUG(3,("copying printer-drivers\n"));
1893 nt_status = connect_dst_pipe(c, &cli_dst, &pipe_hnd_dst,
1894 &ndr_table_spoolss.syntax_id);
1895 if (!NT_STATUS_IS_OK(nt_status)) {
1898 b_dst = pipe_hnd_dst->binding_handle;
1900 /* open print$-share on the src server */
1901 nt_status = connect_to_service(c, &cli_share_src, &cli->dest_ss,
1902 cli->desthost, "print$", "A:");
1903 if (!NT_STATUS_IS_OK(nt_status))
1906 got_src_driver_share = true;
1909 /* open print$-share on the dst server */
1910 nt_status = connect_to_service(c, &cli_share_dst, &cli_dst->dest_ss,
1911 cli_dst->desthost, "print$", "A:");
1912 if (!NT_STATUS_IS_OK(nt_status))
1915 got_dst_driver_share = true;
1918 /* enum src printers */
1919 if (!get_printer_info(pipe_hnd, mem_ctx, 2, argc, argv, &num_printers, &info_enum)) {
1920 nt_status = NT_STATUS_UNSUCCESSFUL;
1924 if (num_printers == 0) {
1925 printf (_("no printers found on server.\n"));
1926 nt_status = NT_STATUS_OK;
1931 /* do something for all printers */
1932 for (p = 0; p < num_printers; p++) {
1934 /* do some initialization */
1935 printername = info_enum[p].info2.printername;
1936 sharename = info_enum[p].info2.sharename;
1938 if (!printername || !sharename) {
1939 nt_status = NT_STATUS_UNSUCCESSFUL;
1943 /* we can reset NT_STATUS here because we do not
1944 get any real NT_STATUS-codes anymore from now on */
1945 nt_status = NT_STATUS_UNSUCCESSFUL;
1947 d_printf(_("migrating printer driver for: [%s] / [%s]\n"),
1948 printername, sharename);
1950 /* open dst printer handle */
1951 if (!net_spoolss_open_printer_ex(pipe_hnd_dst, mem_ctx, sharename,
1952 PRINTER_ALL_ACCESS, cli->user_name, &hnd_dst))
1955 /* check for existing dst printer */
1956 if (!net_spoolss_getprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, 2, &info_dst))
1960 /* open src printer handle */
1961 if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, sharename,
1962 MAXIMUM_ALLOWED_ACCESS,
1963 pipe_hnd->auth->user_name,
1967 /* in a first step call getdriver for each shared printer (per arch)
1968 to get a list of all files that have to be copied */
1970 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1973 if (!net_spoolss_getprinterdriver(pipe_hnd, mem_ctx, &hnd_src,
1974 level, archi_table[i].long_archi,
1975 archi_table[i].version, &drv_info_src))
1978 drivername = drv_info_src.info3.driver_name;
1981 display_print_driver3(&drv_info_src.info3);
1983 /* check arch dir */
1984 nt_status = check_arch_dir(cli_share_dst, archi_table[i].short_archi);
1985 if (!NT_STATUS_IS_OK(nt_status))
1989 /* copy driver-files */
1990 nt_status = copy_print_driver_3(c, mem_ctx, cli_share_src, cli_share_dst,
1991 archi_table[i].short_archi,
1992 &drv_info_src.info3);
1993 if (!NT_STATUS_IS_OK(nt_status))
1998 if (!net_spoolss_addprinterdriver(pipe_hnd_dst, mem_ctx, level, &drv_info_src)) {
1999 nt_status = NT_STATUS_UNSUCCESSFUL;
2003 DEBUGADD(1,("Sucessfully added driver [%s] for printer [%s]\n",
2004 drivername, printername));
2008 if (!drivername || strlen(drivername) == 0) {
2009 DEBUGADD(1,("Did not get driver for printer %s\n",
2015 info_dst.info2.drivername = drivername;
2017 if (!net_spoolss_setprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, 2, &info_dst)) {
2018 nt_status = NT_STATUS_UNSUCCESSFUL;
2022 DEBUGADD(1,("Sucessfully set driver %s for printer %s\n",
2023 drivername, printername));
2026 if (is_valid_policy_hnd(&hnd_dst)) {
2027 dcerpc_spoolss_ClosePrinter(b_dst, mem_ctx, &hnd_dst, &werr);
2031 if (is_valid_policy_hnd(&hnd_src)) {
2032 dcerpc_spoolss_ClosePrinter(b_src, mem_ctx, &hnd_src, &werr);
2036 nt_status = NT_STATUS_OK;
2040 if (is_valid_policy_hnd(&hnd_dst)) {
2041 dcerpc_spoolss_ClosePrinter(b_dst, mem_ctx, &hnd_dst, &werr);
2045 if (is_valid_policy_hnd(&hnd_src)) {
2046 dcerpc_spoolss_ClosePrinter(b_src, mem_ctx, &hnd_src, &werr);
2050 cli_shutdown(cli_dst);
2053 if (got_src_driver_share)
2054 cli_shutdown(cli_share_src);
2056 if (got_dst_driver_share)
2057 cli_shutdown(cli_share_dst);
2064 * Migrate printer-queues from a src to the dst server
2065 * (requires a working "addprinter command" to be installed for the local smbd)
2067 * All parameters are provided by the run_rpc_command function, except for
2068 * argc, argv which are passed through.
2070 * @param c A net_context structure
2071 * @param domain_sid The domain sid aquired from the remote server
2072 * @param cli A cli_state connected to the server.
2073 * @param mem_ctx Talloc context, destoyed on compleation of the function.
2074 * @param argc Standard main() style argc
2075 * @param argv Standard main() style argv. Initial components are already
2078 * @return Normal NTSTATUS return.
2081 NTSTATUS rpc_printer_migrate_printers_internals(struct net_context *c,
2082 const struct dom_sid *domain_sid,
2083 const char *domain_name,
2084 struct cli_state *cli,
2085 struct rpc_pipe_client *pipe_hnd,
2086 TALLOC_CTX *mem_ctx,
2090 struct dcerpc_binding_handle *b_src = pipe_hnd->binding_handle;
2092 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
2093 uint32_t i = 0, num_printers;
2095 union spoolss_PrinterInfo info_dst, info_src;
2096 union spoolss_PrinterInfo *info_enum;
2097 struct cli_state *cli_dst = NULL;
2098 struct policy_handle hnd_dst, hnd_src;
2099 const char *printername, *sharename;
2100 struct rpc_pipe_client *pipe_hnd_dst = NULL;
2101 struct dcerpc_binding_handle *b_dst = NULL;
2102 struct spoolss_SetPrinterInfoCtr info_ctr;
2104 DEBUG(3,("copying printers\n"));
2106 /* connect destination PI_SPOOLSS */
2107 nt_status = connect_dst_pipe(c, &cli_dst, &pipe_hnd_dst,
2108 &ndr_table_spoolss.syntax_id);
2109 if (!NT_STATUS_IS_OK(nt_status)) {
2112 b_dst = pipe_hnd_dst->binding_handle;
2115 if (!get_printer_info(pipe_hnd, mem_ctx, level, argc, argv, &num_printers, &info_enum)) {
2116 nt_status = NT_STATUS_UNSUCCESSFUL;
2120 if (!num_printers) {
2121 printf (_("no printers found on server.\n"));
2122 nt_status = NT_STATUS_OK;
2126 /* do something for all printers */
2127 for (i = 0; i < num_printers; i++) {
2129 struct spoolss_SetPrinterInfo2 info2;
2131 /* do some initialization */
2132 printername = info_enum[i].info2.printername;
2133 sharename = info_enum[i].info2.sharename;
2135 if (!printername || !sharename) {
2136 nt_status = NT_STATUS_UNSUCCESSFUL;
2139 /* we can reset NT_STATUS here because we do not
2140 get any real NT_STATUS-codes anymore from now on */
2141 nt_status = NT_STATUS_UNSUCCESSFUL;
2143 d_printf(_("migrating printer queue for: [%s] / [%s]\n"),
2144 printername, sharename);
2146 /* open dst printer handle */
2147 if (!net_spoolss_open_printer_ex(pipe_hnd_dst, mem_ctx, sharename,
2148 PRINTER_ALL_ACCESS, cli->user_name, &hnd_dst)) {
2150 DEBUG(1,("could not open printer: %s\n", sharename));
2153 /* check for existing dst printer */
2154 if (!net_spoolss_getprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, level, &info_dst)) {
2155 printf (_("could not get printer, creating printer.\n"));
2157 DEBUG(1,("printer already exists: %s\n", sharename));
2158 /* close printer handle here - dst only, not got src yet. */
2159 if (is_valid_policy_hnd(&hnd_dst)) {
2160 dcerpc_spoolss_ClosePrinter(b_dst, mem_ctx, &hnd_dst, &result);
2165 /* now get again src printer ctr via getprinter,
2166 we first need a handle for that */
2168 /* open src printer handle */
2169 if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, sharename,
2170 MAXIMUM_ALLOWED_ACCESS, cli->user_name, &hnd_src))
2173 /* getprinter on the src server */
2174 if (!net_spoolss_getprinter(pipe_hnd, mem_ctx, &hnd_src, level, &info_src))
2177 /* copy each src printer to a dst printer 1:1,
2178 maybe some values have to be changed though */
2179 d_printf(_("creating printer: %s\n"), printername);
2181 info_ctr.level = level;
2182 spoolss_printerinfo2_to_setprinterinfo2(&info_src.info2, &info2);
2183 info_ctr.info.info2 = &info2;
2185 result = rpccli_spoolss_addprinterex(pipe_hnd_dst,
2189 if (W_ERROR_IS_OK(result))
2190 d_printf (_("printer [%s] successfully added.\n"),
2192 else if (W_ERROR_V(result) == W_ERROR_V(WERR_PRINTER_ALREADY_EXISTS))
2193 d_fprintf (stderr, _("printer [%s] already exists.\n"),
2196 d_fprintf (stderr, _("could not create printer [%s]\n"),
2201 /* close printer handles here */
2202 if (is_valid_policy_hnd(&hnd_src)) {
2203 dcerpc_spoolss_ClosePrinter(b_src, mem_ctx, &hnd_src, &result);
2206 if (is_valid_policy_hnd(&hnd_dst)) {
2207 dcerpc_spoolss_ClosePrinter(b_dst, mem_ctx, &hnd_dst, &result);
2211 nt_status = NT_STATUS_OK;
2214 if (is_valid_policy_hnd(&hnd_src)) {
2215 dcerpc_spoolss_ClosePrinter(b_src, mem_ctx, &hnd_src, &result);
2218 if (is_valid_policy_hnd(&hnd_dst)) {
2219 dcerpc_spoolss_ClosePrinter(b_dst, mem_ctx, &hnd_dst, &result);
2223 cli_shutdown(cli_dst);
2229 * Migrate Printer-Settings from a src server to the dst server
2230 * (for this to work, printers and drivers already have to be migrated earlier)
2232 * All parameters are provided by the run_rpc_command function, except for
2233 * argc, argv which are passed through.
2235 * @param c A net_context structure
2236 * @param domain_sid The domain sid aquired from the remote server
2237 * @param cli A cli_state connected to the server.
2238 * @param mem_ctx Talloc context, destoyed on compleation of the function.
2239 * @param argc Standard main() style argc
2240 * @param argv Standard main() style argv. Initial components are already
2243 * @return Normal NTSTATUS return.
2246 NTSTATUS rpc_printer_migrate_settings_internals(struct net_context *c,
2247 const struct dom_sid *domain_sid,
2248 const char *domain_name,
2249 struct cli_state *cli,
2250 struct rpc_pipe_client *pipe_hnd,
2251 TALLOC_CTX *mem_ctx,
2255 struct dcerpc_binding_handle *b_src = pipe_hnd->binding_handle;
2257 /* FIXME: Here the nightmare begins */
2260 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
2261 uint32_t i = 0, j = 0;
2262 uint32_t num_printers;
2264 const char *printername, *sharename;
2265 struct rpc_pipe_client *pipe_hnd_dst = NULL;
2266 struct dcerpc_binding_handle *b_dst = NULL;
2267 struct policy_handle hnd_src, hnd_dst;
2268 union spoolss_PrinterInfo *info_enum;
2269 union spoolss_PrinterInfo info_dst_publish;
2270 union spoolss_PrinterInfo info_dst;
2271 struct cli_state *cli_dst = NULL;
2272 char *devicename = NULL, *unc_name = NULL, *url = NULL;
2273 const char *longname;
2274 const char **keylist = NULL;
2277 ZERO_STRUCT(info_dst_publish);
2279 DEBUG(3,("copying printer settings\n"));
2281 /* connect destination PI_SPOOLSS */
2282 nt_status = connect_dst_pipe(c, &cli_dst, &pipe_hnd_dst,
2283 &ndr_table_spoolss.syntax_id);
2284 if (!NT_STATUS_IS_OK(nt_status)) {
2287 b_dst = pipe_hnd_dst->binding_handle;
2289 /* enum src printers */
2290 if (!get_printer_info(pipe_hnd, mem_ctx, level, argc, argv, &num_printers, &info_enum)) {
2291 nt_status = NT_STATUS_UNSUCCESSFUL;
2295 if (!num_printers) {
2296 printf (_("no printers found on server.\n"));
2297 nt_status = NT_STATUS_OK;
2302 /* needed for dns-strings in regkeys */
2303 longname = get_mydnsfullname();
2305 nt_status = NT_STATUS_UNSUCCESSFUL;
2309 /* do something for all printers */
2310 for (i = 0; i < num_printers; i++) {
2312 uint32_t value_needed;
2313 uint32_t data_needed;
2314 enum winreg_Type type;
2315 struct spoolss_EnumPrinterData r;
2317 /* do some initialization */
2318 printername = info_enum[i].info2.printername;
2319 sharename = info_enum[i].info2.sharename;
2321 if (!printername || !sharename) {
2322 nt_status = NT_STATUS_UNSUCCESSFUL;
2325 /* we can reset NT_STATUS here because we do not
2326 get any real NT_STATUS-codes anymore from now on */
2327 nt_status = NT_STATUS_UNSUCCESSFUL;
2329 d_printf(_("migrating printer settings for: [%s] / [%s]\n"),
2330 printername, sharename);
2333 /* open src printer handle */
2334 if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, sharename,
2335 MAXIMUM_ALLOWED_ACCESS, cli->user_name, &hnd_src))
2338 /* open dst printer handle */
2339 if (!net_spoolss_open_printer_ex(pipe_hnd_dst, mem_ctx, sharename,
2340 PRINTER_ALL_ACCESS, cli_dst->user_name, &hnd_dst))
2343 /* check for existing dst printer */
2344 if (!net_spoolss_getprinter(pipe_hnd_dst, mem_ctx, &hnd_dst,
2349 /* STEP 1: COPY DEVICE-MODE and other
2350 PRINTER_INFO_2-attributes
2353 info_dst.info2 = info_enum[i].info2;
2355 /* why is the port always disconnected when the printer
2356 is correctly installed (incl. driver ???) */
2357 info_dst.info2.portname = SAMBA_PRINTER_PORT_NAME;
2359 /* check if printer is published */
2360 if (info_enum[i].info2.attributes & PRINTER_ATTRIBUTE_PUBLISHED) {
2362 /* check for existing dst printer */
2363 if (!net_spoolss_getprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, 7, &info_dst_publish))
2366 info_dst_publish.info7.action = DSPRINT_PUBLISH;
2368 /* ignore false from setprinter due to WERR_IO_PENDING */
2369 net_spoolss_setprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, 7, &info_dst_publish);
2371 DEBUG(3,("republished printer\n"));
2374 if (info_enum[i].info2.devmode != NULL) {
2376 /* copy devmode (info level 2) */
2377 info_dst.info2.devmode = info_enum[i].info2.devmode;
2379 /* do not copy security descriptor (we have another
2380 * command for that) */
2381 info_dst.info2.secdesc = NULL;
2384 info_dst.info2.devmode.devicename =
2385 talloc_asprintf(mem_ctx, "\\\\%s\\%s",
2386 longname, printername);
2387 if (!info_dst.info2.devmode.devicename) {
2388 nt_status = NT_STATUS_NO_MEMORY;
2392 if (!net_spoolss_setprinter(pipe_hnd_dst, mem_ctx, &hnd_dst,
2396 DEBUGADD(1,("\tSetPrinter of DEVICEMODE succeeded\n"));
2399 /* STEP 2: COPY REGISTRY VALUES */
2401 /* please keep in mind that samba parse_spools gives horribly
2402 crippled results when used to rpccli_spoolss_enumprinterdataex
2403 a win2k3-server. (Bugzilla #1851)
2404 FIXME: IIRC I've seen it too on a win2k-server
2407 r.in.handle = &hnd_src;
2408 r.in.enum_index = 0;
2409 r.in.value_offered = 0;
2410 r.in.data_offered = 0;
2411 r.out.value_name = NULL;
2412 r.out.value_needed = &value_needed;
2415 r.out.data_needed = &data_needed;
2417 /* enumerate data on src handle */
2418 nt_status = dcerpc_spoolss_EnumPrinterData_r(b_src, mem_ctx, &r);
2420 r.in.data_offered = *r.out.data_needed;
2421 r.in.value_offered = *r.out.value_needed;
2422 r.out.data = talloc_zero_array(mem_ctx, uint8_t, r.in.data_offered);
2423 r.out.value_name = talloc_zero_array(mem_ctx, char, r.in.value_offered);
2425 /* loop for all printerdata of "PrinterDriverData" */
2426 while (NT_STATUS_IS_OK(nt_status) && W_ERROR_IS_OK(r.out.result)) {
2430 nt_status = dcerpc_spoolss_EnumPrinterData_r(b_src, mem_ctx, &r);
2432 /* loop for all reg_keys */
2433 if (NT_STATUS_IS_OK(nt_status) && W_ERROR_IS_OK(r.out.result)) {
2436 if (c->opt_verbose) {
2437 struct regval_blob *v;
2439 v = regval_compose(talloc_tos(),
2445 nt_status = NT_STATUS_NO_MEMORY;
2449 display_reg_value(SPOOL_PRINTERDATA_KEY, v);
2454 if (!net_spoolss_setprinterdata(pipe_hnd_dst, mem_ctx,
2455 &hnd_dst, r.out.value_name,
2456 *r.out.type, r.out.data, r.in.data_offered))
2459 DEBUGADD(1,("\tSetPrinterData of [%s] succeeded\n",
2464 /* STEP 3: COPY SUBKEY VALUES */
2466 /* here we need to enum all printer_keys and then work
2467 on the result with enum_printer_key_ex. nt4 does not
2468 respond to enumprinterkey, win2k does, so continue
2469 in case of an error */
2471 if (!net_spoolss_enumprinterkey(pipe_hnd, mem_ctx, &hnd_src, "", &keylist)) {
2472 printf(_("got no key-data\n"));
2477 /* work on a list of printer keys
2478 each key has to be enumerated to get all required
2479 information. information is then set via setprinterdataex-calls */
2481 if (keylist == NULL)
2484 for (i=0; keylist && keylist[i] != NULL; i++) {
2486 const char *subkey = keylist[i];
2488 struct spoolss_PrinterEnumValues *info;
2490 /* enumerate all src subkeys */
2491 if (!net_spoolss_enumprinterdataex(pipe_hnd, mem_ctx, 0,
2497 for (j=0; j < count; j++) {
2499 struct regval_blob *value;
2504 /* although samba replies with sane data in most cases we
2505 should try to avoid writing wrong registry data */
2507 if (strequal(info[j].value_name, SPOOL_REG_PORTNAME) ||
2508 strequal(info[j].value_name, SPOOL_REG_UNCNAME) ||
2509 strequal(info[j].value_name, SPOOL_REG_URL) ||
2510 strequal(info[j].value_name, SPOOL_REG_SHORTSERVERNAME) ||
2511 strequal(info[j].value_name, SPOOL_REG_SERVERNAME)) {
2513 if (strequal(info[j].value_name, SPOOL_REG_PORTNAME)) {
2515 /* although windows uses a multi-sz, we use a sz */
2516 push_reg_sz(mem_ctx, &blob, SAMBA_PRINTER_PORT_NAME);
2519 if (strequal(info[j].value_name, SPOOL_REG_UNCNAME)) {
2521 if (asprintf(&unc_name, "\\\\%s\\%s", longname, sharename) < 0) {
2522 nt_status = NT_STATUS_NO_MEMORY;
2525 push_reg_sz(mem_ctx, &blob, unc_name);
2528 if (strequal(info[j].value_name, SPOOL_REG_URL)) {
2533 /* FIXME: should we really do that ??? */
2534 if (asprintf(&url, "http://%s:631/printers/%s", longname, sharename) < 0) {
2535 nt_status = NT_STATUS_NO_MEMORY;
2538 push_reg_sz(mem_ctx, NULL, &blob, url);
2539 fstrcpy(value.valuename, SPOOL_REG_URL);
2543 if (strequal(info[j].value_name, SPOOL_REG_SERVERNAME)) {
2545 push_reg_sz(mem_ctx, &blob, longname);
2548 if (strequal(info[j].value_name, SPOOL_REG_SHORTSERVERNAME)) {
2550 push_reg_sz(mem_ctx, &blob, global_myname());
2553 value = regval_compose(talloc_tos(),
2556 blob.length == 0 ? NULL : blob.data,
2558 if (value == NULL) {
2559 nt_status = NT_STATUS_NO_MEMORY;
2564 display_reg_value(subkey, value);
2566 /* here we have to set all subkeys on the dst server */
2567 if (!net_spoolss_setprinterdataex(pipe_hnd_dst, mem_ctx, &hnd_dst,
2577 struct regval_blob *v;
2579 v = regval_compose(talloc_tos(),
2583 info[j].data->length);
2585 nt_status = NT_STATUS_NO_MEMORY;
2589 if (c->opt_verbose) {
2590 display_reg_value(subkey, v);
2593 /* here we have to set all subkeys on the dst server */
2594 if (!net_spoolss_setprinterdataex(pipe_hnd_dst, mem_ctx, &hnd_dst,
2602 DEBUGADD(1,("\tSetPrinterDataEx of key [%s\\%s] succeeded\n",
2603 subkey, info[j].value_name));
2608 TALLOC_FREE(keylist);
2610 /* close printer handles here */
2611 if (is_valid_policy_hnd(&hnd_src)) {
2612 dcerpc_spoolss_ClosePrinter(b_src, mem_ctx, &hnd_src, &result);
2615 if (is_valid_policy_hnd(&hnd_dst)) {
2616 dcerpc_spoolss_ClosePrinter(b_dst, mem_ctx, &hnd_dst, &result);
2620 nt_status = NT_STATUS_OK;
2623 SAFE_FREE(devicename);
2625 SAFE_FREE(unc_name);
2627 if (is_valid_policy_hnd(&hnd_src)) {
2628 dcerpc_spoolss_ClosePrinter(b_src, mem_ctx, &hnd_src, &result);
2631 if (is_valid_policy_hnd(&hnd_dst)) {
2632 dcerpc_spoolss_ClosePrinter(b_dst, mem_ctx, &hnd_dst, &result);
2636 cli_shutdown(cli_dst);