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 "utils/net.h"
21 #include "../librpc/gen_ndr/cli_spoolss.h"
22 #include "rpc_client/cli_spoolss.h"
23 #include "rpc_client/init_spoolss.h"
24 #include "nt_printing.h"
26 #include "registry/reg_objects.h"
27 #include "../libcli/security/security.h"
29 /* support itanium as well */
30 static const struct print_architecture_table_node archi_table
[]= {
32 {"Windows 4.0", "WIN40", 0 },
33 {"Windows NT x86", "W32X86", 2 },
34 {"Windows NT x86", "W32X86", 3 },
35 {"Windows NT R4000", "W32MIPS", 2 },
36 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
37 {"Windows NT PowerPC", "W32PPC", 2 },
38 {"Windows IA64", "IA64", 3 },
39 {"Windows x64", "x64", 3 },
45 * This display-printdriver-functions was borrowed from rpcclient/cmd_spoolss.c.
46 * It is here for debugging purpose and should be removed later on.
49 /****************************************************************************
50 Printer info level 3 display function.
51 ****************************************************************************/
53 static void display_print_driver3(struct spoolss_DriverInfo3
*r
)
61 printf(_("Printer Driver Info 3:\n"));
62 printf(_("\tVersion: [%x]\n"), r
->version
);
63 printf(_("\tDriver Name: [%s]\n"), r
->driver_name
);
64 printf(_("\tArchitecture: [%s]\n"), r
->architecture
);
65 printf(_("\tDriver Path: [%s]\n"), r
->driver_path
);
66 printf(_("\tDatafile: [%s]\n"), r
->data_file
);
67 printf(_("\tConfigfile: [%s]\n\n"), r
->config_file
);
68 printf(_("\tHelpfile: [%s]\n\n"), r
->help_file
);
70 for (i
=0; r
->dependent_files
[i
] != NULL
; i
++) {
71 printf(_("\tDependentfiles: [%s]\n"), r
->dependent_files
[i
]);
76 printf(_("\tMonitorname: [%s]\n"), r
->monitor_name
);
77 printf(_("\tDefaultdatatype: [%s]\n\n"), r
->default_datatype
);
80 static void display_reg_value(const char *subkey
, struct regval_blob
*value
)
85 switch(regval_type(value
)) {
87 d_printf(_("\t[%s:%s]: REG_DWORD: 0x%08x\n"), subkey
,
88 regval_name(value
), *((uint32_t *) regval_data_p(value
)));
92 blob
= data_blob_const(regval_data_p(value
), regval_size(value
));
93 pull_reg_sz(talloc_tos(), &blob
, &text
);
97 d_printf(_("\t[%s:%s]: REG_SZ: %s\n"), subkey
, regval_name(value
),
102 d_printf(_("\t[%s:%s]: REG_BINARY: unknown length value not "
104 subkey
, regval_name(value
));
110 blob
= data_blob_const(regval_data_p(value
), regval_size(value
));
112 if (!pull_reg_multi_sz(NULL
, &blob
, &values
)) {
113 d_printf("pull_reg_multi_sz failed\n");
117 printf("%s: REG_MULTI_SZ: \n", regval_name(value
));
118 for (i
=0; values
[i
] != NULL
; i
++) {
119 d_printf("%s\n", values
[i
]);
126 d_printf(_("\t%s: unknown type %d\n"), regval_name(value
),
133 * Copies ACLs, DOS-attributes and timestamps from one
134 * file or directory from one connected share to another connected share
136 * @param c A net_context structure
137 * @param mem_ctx A talloc-context
138 * @param cli_share_src A connected cli_state
139 * @param cli_share_dst A connected cli_state
140 * @param src_file The source file-name
141 * @param dst_file The destination file-name
142 * @param copy_acls Whether to copy acls
143 * @param copy_attrs Whether to copy DOS attributes
144 * @param copy_timestamps Whether to preserve timestamps
145 * @param is_file Whether this file is a file or a dir
147 * @return Normal NTSTATUS return.
150 NTSTATUS
net_copy_fileattr(struct net_context
*c
,
152 struct cli_state
*cli_share_src
,
153 struct cli_state
*cli_share_dst
,
154 const char *src_name
, const char *dst_name
,
155 bool copy_acls
, bool copy_attrs
,
156 bool copy_timestamps
, bool is_file
)
158 NTSTATUS nt_status
= NT_STATUS_UNSUCCESSFUL
;
159 uint16_t fnum_src
= 0;
160 uint16_t fnum_dst
= 0;
161 struct security_descriptor
*sd
= NULL
;
163 time_t f_atime
, f_ctime
, f_mtime
;
166 if (!copy_timestamps
&& !copy_acls
&& !copy_attrs
)
169 /* open file/dir on the originating server */
171 DEBUGADD(3,("opening %s %s on originating server\n",
172 is_file
?"file":"dir", src_name
));
174 if (!NT_STATUS_IS_OK(cli_ntcreate(cli_share_src
, src_name
, 0, READ_CONTROL_ACCESS
, 0,
175 FILE_SHARE_READ
|FILE_SHARE_WRITE
, FILE_OPEN
, 0x0, 0x0, &fnum_src
))) {
176 DEBUGADD(0,("cannot open %s %s on originating server %s\n",
177 is_file
?"file":"dir", src_name
, cli_errstr(cli_share_src
)));
178 nt_status
= cli_nt_error(cli_share_src
);
185 /* get the security descriptor */
186 sd
= cli_query_secdesc(cli_share_src
, fnum_src
, mem_ctx
);
188 DEBUG(0,("failed to get security descriptor: %s\n",
189 cli_errstr(cli_share_src
)));
190 nt_status
= cli_nt_error(cli_share_src
);
194 if (c
->opt_verbose
&& DEBUGLEVEL
>= 3)
195 display_sec_desc(sd
);
199 if (copy_attrs
|| copy_timestamps
) {
201 /* get file attributes */
202 if (!NT_STATUS_IS_OK(cli_getattrE(cli_share_src
, fnum_src
, &attr
, NULL
,
203 &f_ctime
, &f_atime
, &f_mtime
))) {
204 DEBUG(0,("failed to get file-attrs: %s\n",
205 cli_errstr(cli_share_src
)));
206 nt_status
= cli_nt_error(cli_share_src
);
212 /* open the file/dir on the destination server */
214 if (!NT_STATUS_IS_OK(cli_ntcreate(cli_share_dst
, dst_name
, 0, WRITE_DAC_ACCESS
| WRITE_OWNER_ACCESS
, 0,
215 FILE_SHARE_READ
|FILE_SHARE_WRITE
, FILE_OPEN
, 0x0, 0x0, &fnum_dst
))) {
216 DEBUG(0,("failed to open %s on the destination server: %s: %s\n",
217 is_file
?"file":"dir", dst_name
, cli_errstr(cli_share_dst
)));
218 nt_status
= cli_nt_error(cli_share_dst
);
222 if (copy_timestamps
) {
225 if (!NT_STATUS_IS_OK(cli_setattrE(cli_share_dst
, fnum_dst
, f_ctime
, f_atime
, f_mtime
))) {
226 DEBUG(0,("failed to set file-attrs (timestamps): %s\n",
227 cli_errstr(cli_share_dst
)));
228 nt_status
= cli_nt_error(cli_share_dst
);
237 status
= cli_set_secdesc(cli_share_dst
, fnum_dst
, sd
);
238 if (!NT_STATUS_IS_OK(status
)) {
239 DEBUG(0, ("could not set secdesc on %s: %s\n",
240 dst_name
, nt_errstr(status
)));
249 if (!NT_STATUS_IS_OK(cli_setatr(cli_share_dst
, dst_name
, attr
, 0))) {
250 DEBUG(0,("failed to set file-attrs: %s\n",
251 cli_errstr(cli_share_dst
)));
252 nt_status
= cli_nt_error(cli_share_dst
);
260 if (!NT_STATUS_IS_OK(cli_close(cli_share_src
, fnum_src
))) {
262 _("could not close %s on originating server: %s\n"),
263 is_file
?"file":"dir", cli_errstr(cli_share_src
));
264 nt_status
= cli_nt_error(cli_share_src
);
268 if (!NT_STATUS_IS_OK(cli_close(cli_share_dst
, fnum_dst
))) {
270 _("could not close %s on destination server: %s\n"),
271 is_file
?"file":"dir", cli_errstr(cli_share_dst
));
272 nt_status
= cli_nt_error(cli_share_dst
);
277 nt_status
= NT_STATUS_OK
;
283 cli_close(cli_share_src
, fnum_src
);
286 cli_close(cli_share_dst
, fnum_dst
);
292 * Copy a file or directory from a connected share to another connected share
294 * @param c A net_context structure
295 * @param mem_ctx A talloc-context
296 * @param cli_share_src A connected cli_state
297 * @param cli_share_dst A connected cli_state
298 * @param src_file The source file-name
299 * @param dst_file The destination file-name
300 * @param copy_acls Whether to copy acls
301 * @param copy_attrs Whether to copy DOS attributes
302 * @param copy_timestamps Whether to preserve timestamps
303 * @param is_file Whether this file is a file or a dir
305 * @return Normal NTSTATUS return.
308 NTSTATUS
net_copy_file(struct net_context
*c
,
310 struct cli_state
*cli_share_src
,
311 struct cli_state
*cli_share_dst
,
312 const char *src_name
, const char *dst_name
,
313 bool copy_acls
, bool copy_attrs
,
314 bool copy_timestamps
, bool is_file
)
316 NTSTATUS nt_status
= NT_STATUS_UNSUCCESSFUL
;
317 uint16_t fnum_src
= 0;
318 uint16_t fnum_dst
= 0;
319 static int io_bufsize
= 64512;
320 int read_size
= io_bufsize
;
325 if (!src_name
|| !dst_name
)
328 if (cli_share_src
== NULL
|| cli_share_dst
== NULL
)
331 /* open on the originating server */
332 DEBUGADD(3,("opening %s %s on originating server\n",
333 is_file
? "file":"dir", src_name
));
335 nt_status
= cli_open(cli_share_src
, src_name
, O_RDONLY
, DENY_NONE
, &fnum_src
);
337 nt_status
= cli_ntcreate(cli_share_src
, src_name
, 0, READ_CONTROL_ACCESS
, 0,
338 FILE_SHARE_READ
|FILE_SHARE_WRITE
, FILE_OPEN
, 0x0, 0x0, &fnum_src
);
340 if (!NT_STATUS_IS_OK(nt_status
)) {
341 DEBUGADD(0,("cannot open %s %s on originating server %s\n",
342 is_file
? "file":"dir",
343 src_name
, cli_errstr(cli_share_src
)));
350 /* open file on the destination server */
351 DEBUGADD(3,("opening file %s on destination server\n", dst_name
));
352 nt_status
= cli_open(cli_share_dst
, dst_name
,
353 O_RDWR
|O_CREAT
|O_TRUNC
, DENY_NONE
, &fnum_dst
);
355 if (!NT_STATUS_IS_OK(nt_status
)) {
356 DEBUGADD(1,("cannot create file %s on destination server: %s\n",
357 dst_name
, cli_errstr(cli_share_dst
)));
361 /* allocate memory */
362 if (!(data
= (char *)SMB_MALLOC(read_size
))) {
363 d_fprintf(stderr
, _("malloc fail for size %d\n"),
365 nt_status
= NT_STATUS_NO_MEMORY
;
372 if (c
->opt_verbose
) {
374 d_printf(_("copying [\\\\%s\\%s%s] => [\\\\%s\\%s%s] "
375 "%s ACLs and %s DOS Attributes %s\n"),
376 cli_share_src
->desthost
, cli_share_src
->share
, src_name
,
377 cli_share_dst
->desthost
, cli_share_dst
->share
, dst_name
,
378 copy_acls
? _("with") : _("without"),
379 copy_attrs
? _("with") : _("without"),
380 copy_timestamps
? _("(preserving timestamps)") : "" );
388 n
= cli_read(cli_share_src
, fnum_src
, data
, nread
,
394 ret
= cli_write(cli_share_dst
, fnum_dst
, 0, data
,
398 d_fprintf(stderr
, _("Error writing file: %s\n"),
399 cli_errstr(cli_share_dst
));
400 nt_status
= cli_nt_error(cli_share_dst
);
408 if (!is_file
&& !NT_STATUS_IS_OK(cli_chkpath(cli_share_dst
, dst_name
))) {
411 DEBUGADD(3,("creating dir %s on the destination server\n",
414 if (!NT_STATUS_IS_OK(cli_mkdir(cli_share_dst
, dst_name
))) {
415 DEBUG(0,("cannot create directory %s: %s\n",
416 dst_name
, cli_errstr(cli_share_dst
)));
417 nt_status
= NT_STATUS_NO_SUCH_FILE
;
420 if (!NT_STATUS_IS_OK(cli_chkpath(cli_share_dst
, dst_name
))) {
422 _("cannot check for directory %s: %s\n"),
423 dst_name
, cli_errstr(cli_share_dst
));
430 if (!NT_STATUS_IS_OK(cli_close(cli_share_src
, fnum_src
))) {
432 _("could not close file on originating server: %s\n"),
433 cli_errstr(cli_share_src
));
434 nt_status
= cli_nt_error(cli_share_src
);
438 if (is_file
&& !NT_STATUS_IS_OK(cli_close(cli_share_dst
, fnum_dst
))) {
440 _("could not close file on destination server: %s\n"),
441 cli_errstr(cli_share_dst
));
442 nt_status
= cli_nt_error(cli_share_dst
);
446 /* possibly we have to copy some file-attributes / acls / sd */
447 nt_status
= net_copy_fileattr(c
, mem_ctx
, cli_share_src
, cli_share_dst
,
448 src_name
, dst_name
, copy_acls
,
449 copy_attrs
, copy_timestamps
, is_file
);
450 if (!NT_STATUS_IS_OK(nt_status
))
454 nt_status
= NT_STATUS_OK
;
460 cli_close(cli_share_src
, fnum_src
);
463 cli_close(cli_share_dst
, fnum_dst
);
471 * Copy a driverfile from on connected share to another connected share
472 * This silently assumes that a driver-file is picked up from
474 * \\src_server\print$\{arch}\{version}\file
478 * \\dst_server\print$\{arch}\file
480 * to be added via setdriver-calls later.
481 * @param c A net_context structure
482 * @param mem_ctx A talloc-context
483 * @param cli_share_src A cli_state connected to source print$-share
484 * @param cli_share_dst A cli_state connected to destination print$-share
485 * @param file The file-name to be copied
486 * @param short_archi The name of the driver-architecture (short form)
488 * @return Normal NTSTATUS return.
491 static NTSTATUS
net_copy_driverfile(struct net_context
*c
,
493 struct cli_state
*cli_share_src
,
494 struct cli_state
*cli_share_dst
,
495 const char *file
, const char *short_archi
) {
500 char *version
= NULL
;
501 char *filename
= NULL
;
508 /* scroll through the file until we have the part
509 beyond archi_table.short_archi */
511 while (next_token_talloc(mem_ctx
, &p
, &tok
, "\\")) {
512 if (strequal(tok
, short_archi
)) {
513 next_token_talloc(mem_ctx
, &p
, &version
, "\\");
514 next_token_talloc(mem_ctx
, &p
, &filename
, "\\");
518 if (version
== NULL
|| filename
== NULL
) {
519 return NT_STATUS_UNSUCCESSFUL
;
522 /* build source file name */
523 src_name
= talloc_asprintf(mem_ctx
, "\\%s\\%s\\%s",
524 short_archi
, version
, filename
);
525 if (src_name
== NULL
) {
526 return NT_STATUS_NO_MEMORY
;
529 /* create destination file name */
530 dst_name
= talloc_asprintf(mem_ctx
, "\\%s\\%s", short_archi
, filename
);
531 if (dst_name
== NULL
) {
532 return NT_STATUS_NO_MEMORY
;
536 /* finally copy the file */
537 return net_copy_file(c
, mem_ctx
, cli_share_src
, cli_share_dst
,
538 src_name
, dst_name
, false, false, false, true);
542 * Check for existing Architecture directory on a given server
544 * @param cli_share A cli_state connected to a print$-share
545 * @param short_archi The Architecture for the print-driver
547 * @return Normal NTSTATUS return.
550 static NTSTATUS
check_arch_dir(struct cli_state
*cli_share
, const char *short_archi
)
553 NTSTATUS nt_status
= NT_STATUS_UNSUCCESSFUL
;
556 if (asprintf(&dir
, "\\%s", short_archi
) < 0) {
557 return NT_STATUS_NO_MEMORY
;
560 DEBUG(10,("creating print-driver dir for architecture: %s\n",
563 if (!NT_STATUS_IS_OK(cli_mkdir(cli_share
, dir
))) {
564 DEBUG(1,("cannot create directory %s: %s\n",
565 dir
, cli_errstr(cli_share
)));
566 nt_status
= NT_STATUS_NO_SUCH_FILE
;
569 if (!NT_STATUS_IS_OK(cli_chkpath(cli_share
, dir
))) {
570 d_fprintf(stderr
, _("cannot check %s: %s\n"),
571 dir
, cli_errstr(cli_share
));
575 nt_status
= NT_STATUS_OK
;
583 * Copy a print-driver (level 3) from one connected print$-share to another
584 * connected print$-share
586 * @param c A net_context structure
587 * @param mem_ctx A talloc-context
588 * @param cli_share_src A cli_state connected to a print$-share
589 * @param cli_share_dst A cli_state connected to a print$-share
590 * @param short_archi The Architecture for the print-driver
591 * @param i1 The DRIVER_INFO_3-struct
593 * @return Normal NTSTATUS return.
596 static NTSTATUS
copy_print_driver_3(struct net_context
*c
,
598 struct cli_state
*cli_share_src
,
599 struct cli_state
*cli_share_dst
,
600 const char *short_archi
,
601 struct spoolss_DriverInfo3
*r
)
603 NTSTATUS nt_status
= NT_STATUS_UNSUCCESSFUL
;
611 d_printf(_("copying driver: [%s], for architecture: [%s], "
613 r
->driver_name
, short_archi
, r
->version
);
615 nt_status
= net_copy_driverfile(c
, mem_ctx
, cli_share_src
, cli_share_dst
,
616 r
->driver_path
, short_archi
);
617 if (!NT_STATUS_IS_OK(nt_status
))
620 nt_status
= net_copy_driverfile(c
, mem_ctx
, cli_share_src
, cli_share_dst
,
621 r
->data_file
, short_archi
);
622 if (!NT_STATUS_IS_OK(nt_status
))
625 nt_status
= net_copy_driverfile(c
, mem_ctx
, cli_share_src
, cli_share_dst
,
626 r
->config_file
, short_archi
);
627 if (!NT_STATUS_IS_OK(nt_status
))
630 nt_status
= net_copy_driverfile(c
, mem_ctx
, cli_share_src
, cli_share_dst
,
631 r
->help_file
, short_archi
);
632 if (!NT_STATUS_IS_OK(nt_status
))
635 for (i
=0; r
->dependent_files
[i
] != NULL
; i
++) {
637 nt_status
= net_copy_driverfile(c
, mem_ctx
,
638 cli_share_src
, cli_share_dst
,
639 r
->dependent_files
[i
], short_archi
);
640 if (!NT_STATUS_IS_OK(nt_status
)) {
649 * net_spoolss-functions
650 * =====================
652 * the net_spoolss-functions aim to simplify spoolss-client-functions
653 * required during the migration-process wrt buffer-sizes, returned
656 * this greatly reduces the complexitiy of the migrate-functions.
660 static bool net_spoolss_enum_printers(struct rpc_pipe_client
*pipe_hnd
,
665 uint32_t *num_printers
,
666 union spoolss_PrinterInfo
**info
)
672 result
= rpccli_spoolss_enumprinters(pipe_hnd
, mem_ctx
,
679 if (!W_ERROR_IS_OK(result
)) {
680 printf(_("cannot enum printers: %s\n"), win_errstr(result
));
687 static bool net_spoolss_open_printer_ex(struct rpc_pipe_client
*pipe_hnd
,
689 const char *printername
,
690 uint32_t access_required
,
691 const char *username
,
692 struct policy_handle
*hnd
)
695 fstring printername2
;
697 fstrcpy(printername2
, pipe_hnd
->srv_name_slash
);
698 fstrcat(printername2
, "\\");
699 fstrcat(printername2
, printername
);
701 DEBUG(10,("connecting to: %s as %s for %s and access: %x\n",
702 pipe_hnd
->srv_name_slash
, username
, printername2
, access_required
));
705 result
= rpccli_spoolss_openprinter_ex(pipe_hnd
, mem_ctx
,
710 /* be more verbose */
711 if (W_ERROR_V(result
) == W_ERROR_V(WERR_ACCESS_DENIED
)) {
713 _("no access to printer [%s] on [%s] for user [%s] "
715 printername2
, pipe_hnd
->srv_name_slash
, username
);
719 if (!W_ERROR_IS_OK(result
)) {
720 d_fprintf(stderr
,_("cannot open printer %s on server %s: %s\n"),
721 printername2
, pipe_hnd
->srv_name_slash
, win_errstr(result
));
725 DEBUG(2,("got printer handle for printer: %s, server: %s\n",
726 printername2
, pipe_hnd
->srv_name_slash
));
731 static bool net_spoolss_getprinter(struct rpc_pipe_client
*pipe_hnd
,
733 struct policy_handle
*hnd
,
735 union spoolss_PrinterInfo
*info
)
739 /* getprinter call */
740 result
= rpccli_spoolss_getprinter(pipe_hnd
, mem_ctx
,
745 if (!W_ERROR_IS_OK(result
)) {
746 printf(_("cannot get printer-info: %s\n"), win_errstr(result
));
753 static bool net_spoolss_setprinter(struct rpc_pipe_client
*pipe_hnd
,
755 struct policy_handle
*hnd
,
757 union spoolss_PrinterInfo
*info
)
761 struct spoolss_SetPrinterInfoCtr info_ctr
;
762 struct spoolss_SetPrinterInfo2 info2
;
763 struct spoolss_DevmodeContainer devmode_ctr
;
764 struct sec_desc_buf secdesc_ctr
;
766 ZERO_STRUCT(devmode_ctr
);
767 ZERO_STRUCT(secdesc_ctr
);
769 /* setprinter call */
771 info_ctr
.level
= level
;
774 info_ctr
.info
.info0
= (struct spoolss_SetPrinterInfo0
*)
775 (void *)&info
->info0
;
778 info_ctr
.info
.info1
= (struct spoolss_SetPrinterInfo1
*)
779 (void *)&info
->info1
;
782 spoolss_printerinfo2_to_setprinterinfo2(&info
->info2
, &info2
);
783 info_ctr
.info
.info2
= &info2
;
786 info_ctr
.info
.info3
= (struct spoolss_SetPrinterInfo3
*)
787 (void *)&info
->info3
;
790 info_ctr
.info
.info4
= (struct spoolss_SetPrinterInfo4
*)
791 (void *)&info
->info4
;
794 info_ctr
.info
.info5
= (struct spoolss_SetPrinterInfo5
*)
795 (void *)&info
->info5
;
798 info_ctr
.info
.info6
= (struct spoolss_SetPrinterInfo6
*)
799 (void *)&info
->info6
;
802 info_ctr
.info
.info7
= (struct spoolss_SetPrinterInfo7
*)
803 (void *)&info
->info7
;
807 info_ctr
.info
.info8
= (struct spoolss_SetPrinterInfo8
*)
808 (void *)&info
->info8
;
811 info_ctr
.info
.info9
= (struct spoolss_SetPrinterInfo9
*)
812 (void *)&info
->info9
;
819 status
= rpccli_spoolss_SetPrinter(pipe_hnd
, mem_ctx
,
827 if (!W_ERROR_IS_OK(result
)) {
828 printf(_("cannot set printer-info: %s\n"), win_errstr(result
));
836 static bool net_spoolss_setprinterdata(struct rpc_pipe_client
*pipe_hnd
,
838 struct policy_handle
*hnd
,
839 const char *value_name
,
840 enum winreg_Type type
,
847 /* setprinterdata call */
848 status
= rpccli_spoolss_SetPrinterData(pipe_hnd
, mem_ctx
,
856 if (!W_ERROR_IS_OK(result
)) {
857 printf (_("unable to set printerdata: %s\n"),
866 static bool net_spoolss_enumprinterkey(struct rpc_pipe_client
*pipe_hnd
,
868 struct policy_handle
*hnd
,
870 const char ***keylist
)
874 /* enumprinterkey call */
875 result
= rpccli_spoolss_enumprinterkey(pipe_hnd
, mem_ctx
, hnd
, keyname
, keylist
, 0);
877 if (!W_ERROR_IS_OK(result
)) {
878 printf(_("enumprinterkey failed: %s\n"), win_errstr(result
));
885 static bool net_spoolss_enumprinterdataex(struct rpc_pipe_client
*pipe_hnd
,
888 struct policy_handle
*hnd
,
891 struct spoolss_PrinterEnumValues
**info
)
895 /* enumprinterdataex call */
896 result
= rpccli_spoolss_enumprinterdataex(pipe_hnd
, mem_ctx
,
903 if (!W_ERROR_IS_OK(result
)) {
904 printf(_("enumprinterdataex failed: %s\n"), win_errstr(result
));
912 static bool net_spoolss_setprinterdataex(struct rpc_pipe_client
*pipe_hnd
,
914 struct policy_handle
*hnd
,
916 struct regval_blob
*value
)
921 /* setprinterdataex call */
922 status
= rpccli_spoolss_SetPrinterDataEx(pipe_hnd
, mem_ctx
,
927 regval_data_p(value
),
931 if (!W_ERROR_IS_OK(result
)) {
932 printf(_("could not set printerdataex: %s\n"),
940 static bool net_spoolss_enumforms(struct rpc_pipe_client
*pipe_hnd
,
942 struct policy_handle
*hnd
,
945 union spoolss_FormInfo
**forms
)
950 result
= rpccli_spoolss_enumforms(pipe_hnd
, mem_ctx
,
956 if (!W_ERROR_IS_OK(result
)) {
957 printf(_("could not enum forms: %s\n"), win_errstr(result
));
964 static bool net_spoolss_enumprinterdrivers (struct rpc_pipe_client
*pipe_hnd
,
966 uint32_t level
, const char *env
,
968 union spoolss_DriverInfo
**info
)
972 /* enumprinterdrivers call */
973 result
= rpccli_spoolss_enumprinterdrivers(pipe_hnd
, mem_ctx
,
974 pipe_hnd
->srv_name_slash
,
980 if (!W_ERROR_IS_OK(result
)) {
981 if (W_ERROR_V(result
) != W_ERROR_V(WERR_INVALID_ENVIRONMENT
)) {
982 printf(_("cannot enum drivers for environment %s: %s\n"), env
,
986 printf(_("Server does not support environment [%s]\n"),
994 static bool net_spoolss_getprinterdriver(struct rpc_pipe_client
*pipe_hnd
,
996 struct policy_handle
*hnd
, uint32_t level
,
997 const char *env
, int version
,
998 union spoolss_DriverInfo
*info
)
1001 uint32_t server_major_version
;
1002 uint32_t server_minor_version
;
1004 /* getprinterdriver call */
1005 result
= rpccli_spoolss_getprinterdriver2(pipe_hnd
, mem_ctx
,
1013 &server_major_version
,
1014 &server_minor_version
);
1015 if (!W_ERROR_IS_OK(result
)) {
1016 DEBUG(1,("cannot get driver (for architecture: %s): %s\n",
1017 env
, win_errstr(result
)));
1018 if (W_ERROR_V(result
) != W_ERROR_V(WERR_UNKNOWN_PRINTER_DRIVER
) &&
1019 W_ERROR_V(result
) != W_ERROR_V(WERR_INVALID_ENVIRONMENT
)) {
1020 printf(_("cannot get driver: %s\n"),
1021 win_errstr(result
));
1030 static bool net_spoolss_addprinterdriver(struct rpc_pipe_client
*pipe_hnd
,
1031 TALLOC_CTX
*mem_ctx
, uint32_t level
,
1032 union spoolss_DriverInfo
*info
)
1036 struct spoolss_AddDriverInfoCtr info_ctr
;
1038 info_ctr
.level
= level
;
1042 info_ctr
.info
.info2
= (struct spoolss_AddDriverInfo2
*)
1043 (void *)&info
->info2
;
1046 info_ctr
.info
.info3
= (struct spoolss_AddDriverInfo3
*)
1047 (void *)&info
->info3
;
1050 printf(_("unsupported info level: %d\n"), level
);
1054 /* addprinterdriver call */
1055 status
= rpccli_spoolss_AddPrinterDriver(pipe_hnd
, mem_ctx
,
1056 pipe_hnd
->srv_name_slash
,
1059 /* be more verbose */
1060 if (W_ERROR_V(result
) == W_ERROR_V(WERR_ACCESS_DENIED
)) {
1061 printf(_("You are not allowed to add drivers\n"));
1064 if (!W_ERROR_IS_OK(result
)) {
1065 printf(_("cannot add driver: %s\n"), win_errstr(result
));
1073 * abstraction function to get uint32_t num_printers and PRINTER_INFO_CTR ctr
1074 * for a single printer or for all printers depending on argc/argv
1077 static bool get_printer_info(struct rpc_pipe_client
*pipe_hnd
,
1078 TALLOC_CTX
*mem_ctx
,
1082 uint32_t *num_printers
,
1083 union spoolss_PrinterInfo
**info_p
)
1085 struct policy_handle hnd
;
1087 /* no arguments given, enumerate all printers */
1090 if (!net_spoolss_enum_printers(pipe_hnd
, mem_ctx
, NULL
,
1091 PRINTER_ENUM_LOCAL
|PRINTER_ENUM_SHARED
,
1092 level
, num_printers
, info_p
))
1098 /* argument given, get a single printer by name */
1099 if (!net_spoolss_open_printer_ex(pipe_hnd
, mem_ctx
, argv
[0],
1100 MAXIMUM_ALLOWED_ACCESS
,
1101 pipe_hnd
->auth
->user_name
,
1105 *info_p
= talloc_zero(mem_ctx
, union spoolss_PrinterInfo
);
1106 if (*info_p
== NULL
) {
1110 if (!net_spoolss_getprinter(pipe_hnd
, mem_ctx
, &hnd
, level
, *info_p
)) {
1111 rpccli_spoolss_ClosePrinter(pipe_hnd
, mem_ctx
, &hnd
, NULL
);
1115 rpccli_spoolss_ClosePrinter(pipe_hnd
, mem_ctx
, &hnd
, NULL
);
1120 DEBUG(3,("got %d printers\n", *num_printers
));
1127 * List print-queues (including local printers that are not shared)
1129 * All parameters are provided by the run_rpc_command function, except for
1130 * argc, argv which are passed through.
1132 * @param c A net_context structure
1133 * @param domain_sid The domain sid aquired from the remote server
1134 * @param cli A cli_state connected to the server.
1135 * @param mem_ctx Talloc context, destoyed on compleation of the function.
1136 * @param argc Standard main() style argc
1137 * @param argv Standard main() style argv. Initial components are already
1140 * @return Normal NTSTATUS return.
1143 NTSTATUS
rpc_printer_list_internals(struct net_context
*c
,
1144 const struct dom_sid
*domain_sid
,
1145 const char *domain_name
,
1146 struct cli_state
*cli
,
1147 struct rpc_pipe_client
*pipe_hnd
,
1148 TALLOC_CTX
*mem_ctx
,
1152 NTSTATUS nt_status
= NT_STATUS_UNSUCCESSFUL
;
1153 uint32_t i
, num_printers
;
1155 const char *printername
, *sharename
;
1156 union spoolss_PrinterInfo
*info
;
1158 printf("listing printers\n");
1160 if (!get_printer_info(pipe_hnd
, mem_ctx
, level
, argc
, argv
, &num_printers
, &info
))
1163 for (i
= 0; i
< num_printers
; i
++) {
1165 /* do some initialization */
1166 printername
= info
[i
].info2
.printername
;
1167 sharename
= info
[i
].info2
.sharename
;
1169 if (printername
&& sharename
) {
1170 d_printf(_("printer %d: %s, shared as: %s\n"),
1171 i
+1, printername
, sharename
);
1175 return NT_STATUS_OK
;
1179 * List printer-drivers from a server
1181 * All parameters are provided by the run_rpc_command function, except for
1182 * argc, argv which are passed through.
1184 * @param c A net_context structure
1185 * @param domain_sid The domain sid aquired from the remote server
1186 * @param cli A cli_state connected to the server.
1187 * @param mem_ctx Talloc context, destoyed on compleation of the function.
1188 * @param argc Standard main() style argc
1189 * @param argv Standard main() style argv. Initial components are already
1192 * @return Normal NTSTATUS return.
1195 NTSTATUS
rpc_printer_driver_list_internals(struct net_context
*c
,
1196 const struct dom_sid
*domain_sid
,
1197 const char *domain_name
,
1198 struct cli_state
*cli
,
1199 struct rpc_pipe_client
*pipe_hnd
,
1200 TALLOC_CTX
*mem_ctx
,
1204 NTSTATUS nt_status
= NT_STATUS_UNSUCCESSFUL
;
1207 union spoolss_DriverInfo
*info
;
1210 printf(_("listing printer-drivers\n"));
1212 for (i
=0; archi_table
[i
].long_archi
!=NULL
; i
++) {
1214 uint32_t num_drivers
;
1216 /* enum remote drivers */
1217 if (!net_spoolss_enumprinterdrivers(pipe_hnd
, mem_ctx
, level
,
1218 archi_table
[i
].long_archi
,
1219 &num_drivers
, &info
)) {
1220 nt_status
= NT_STATUS_UNSUCCESSFUL
;
1224 if (num_drivers
== 0) {
1225 d_printf(_("no drivers found on server for "
1226 "architecture: [%s].\n"),
1227 archi_table
[i
].long_archi
);
1231 d_printf(_("got %d printer-drivers for architecture: [%s]\n"),
1232 num_drivers
, archi_table
[i
].long_archi
);
1235 /* do something for all drivers for architecture */
1236 for (d
= 0; d
< num_drivers
; d
++) {
1237 display_print_driver3(&info
[d
].info3
);
1241 nt_status
= NT_STATUS_OK
;
1249 * Publish print-queues with args-wrapper
1251 * @param cli A cli_state connected to the server.
1252 * @param mem_ctx Talloc context, destoyed on compleation of the function.
1253 * @param argc Standard main() style argc
1254 * @param argv Standard main() style argv. Initial components are already
1258 * @return Normal NTSTATUS return.
1261 static NTSTATUS
rpc_printer_publish_internals_args(struct rpc_pipe_client
*pipe_hnd
,
1262 TALLOC_CTX
*mem_ctx
,
1267 NTSTATUS nt_status
= NT_STATUS_UNSUCCESSFUL
;
1268 uint32_t i
, num_printers
;
1270 const char *printername
, *sharename
;
1271 union spoolss_PrinterInfo
*info_enum
;
1272 union spoolss_PrinterInfo info
;
1273 struct spoolss_SetPrinterInfoCtr info_ctr
;
1274 struct spoolss_DevmodeContainer devmode_ctr
;
1275 struct sec_desc_buf secdesc_ctr
;
1276 struct policy_handle hnd
;
1278 const char *action_str
;
1280 if (!get_printer_info(pipe_hnd
, mem_ctx
, 2, argc
, argv
, &num_printers
, &info_enum
))
1283 for (i
= 0; i
< num_printers
; i
++) {
1285 /* do some initialization */
1286 printername
= info_enum
[i
].info2
.printername
;
1287 sharename
= info_enum
[i
].info2
.sharename
;
1288 if (!printername
|| !sharename
) {
1292 /* open printer handle */
1293 if (!net_spoolss_open_printer_ex(pipe_hnd
, mem_ctx
, sharename
,
1294 PRINTER_ALL_ACCESS
, pipe_hnd
->auth
->user_name
, &hnd
))
1297 /* check for existing dst printer */
1298 if (!net_spoolss_getprinter(pipe_hnd
, mem_ctx
, &hnd
, level
, &info
))
1301 /* check action and set string */
1303 case DSPRINT_PUBLISH
:
1304 action_str
= N_("published");
1306 case DSPRINT_UPDATE
:
1307 action_str
= N_("updated");
1309 case DSPRINT_UNPUBLISH
:
1310 action_str
= N_("unpublished");
1313 action_str
= N_("unknown action");
1314 printf(_("unkown action: %d\n"), action
);
1318 info
.info7
.action
= action
;
1320 info_ctr
.info
.info7
= (struct spoolss_SetPrinterInfo7
*)
1321 (void *)&info
.info7
;
1323 ZERO_STRUCT(devmode_ctr
);
1324 ZERO_STRUCT(secdesc_ctr
);
1326 nt_status
= rpccli_spoolss_SetPrinter(pipe_hnd
, mem_ctx
,
1334 if (!W_ERROR_IS_OK(result
) && !W_ERROR_EQUAL(result
, WERR_IO_PENDING
)) {
1335 if ((action
== DSPRINT_UPDATE
) && W_ERROR_EQUAL(result
, W_ERROR(0x80070002))) {
1336 printf(_("printer not published yet\n"));
1338 printf(_("cannot set printer-info: %s\n"),
1339 win_errstr(result
));
1344 printf(_("successfully %s printer %s in Active Directory\n"),
1345 action_str
, sharename
);
1348 nt_status
= NT_STATUS_OK
;
1351 if (is_valid_policy_hnd(&hnd
))
1352 rpccli_spoolss_ClosePrinter(pipe_hnd
, mem_ctx
, &hnd
, NULL
);
1357 NTSTATUS
rpc_printer_publish_publish_internals(struct net_context
*c
,
1358 const struct dom_sid
*domain_sid
,
1359 const char *domain_name
,
1360 struct cli_state
*cli
,
1361 struct rpc_pipe_client
*pipe_hnd
,
1362 TALLOC_CTX
*mem_ctx
,
1366 return rpc_printer_publish_internals_args(pipe_hnd
, mem_ctx
, argc
, argv
, DSPRINT_PUBLISH
);
1369 NTSTATUS
rpc_printer_publish_unpublish_internals(struct net_context
*c
,
1370 const struct dom_sid
*domain_sid
,
1371 const char *domain_name
,
1372 struct cli_state
*cli
,
1373 struct rpc_pipe_client
*pipe_hnd
,
1374 TALLOC_CTX
*mem_ctx
,
1378 return rpc_printer_publish_internals_args(pipe_hnd
, mem_ctx
, argc
, argv
, DSPRINT_UNPUBLISH
);
1381 NTSTATUS
rpc_printer_publish_update_internals(struct net_context
*c
,
1382 const struct dom_sid
*domain_sid
,
1383 const char *domain_name
,
1384 struct cli_state
*cli
,
1385 struct rpc_pipe_client
*pipe_hnd
,
1386 TALLOC_CTX
*mem_ctx
,
1390 return rpc_printer_publish_internals_args(pipe_hnd
, mem_ctx
, argc
, argv
, DSPRINT_UPDATE
);
1394 * List print-queues w.r.t. their publishing state
1396 * All parameters are provided by the run_rpc_command function, except for
1397 * argc, argv which are passed through.
1399 * @param c A net_context structure
1400 * @param domain_sid The domain sid aquired from the remote server
1401 * @param cli A cli_state connected to the server.
1402 * @param mem_ctx Talloc context, destoyed on compleation of the function.
1403 * @param argc Standard main() style argc
1404 * @param argv Standard main() style argv. Initial components are already
1407 * @return Normal NTSTATUS return.
1410 NTSTATUS
rpc_printer_publish_list_internals(struct net_context
*c
,
1411 const struct dom_sid
*domain_sid
,
1412 const char *domain_name
,
1413 struct cli_state
*cli
,
1414 struct rpc_pipe_client
*pipe_hnd
,
1415 TALLOC_CTX
*mem_ctx
,
1419 NTSTATUS nt_status
= NT_STATUS_UNSUCCESSFUL
;
1420 uint32_t i
, num_printers
;
1422 const char *printername
, *sharename
;
1423 union spoolss_PrinterInfo
*info_enum
;
1424 union spoolss_PrinterInfo info
;
1425 struct policy_handle hnd
;
1428 if (!get_printer_info(pipe_hnd
, mem_ctx
, 2, argc
, argv
, &num_printers
, &info_enum
))
1431 for (i
= 0; i
< num_printers
; i
++) {
1433 /* do some initialization */
1434 printername
= info_enum
[i
].info2
.printername
;
1435 sharename
= info_enum
[i
].info2
.sharename
;
1437 if (!printername
|| !sharename
) {
1441 /* open printer handle */
1442 if (!net_spoolss_open_printer_ex(pipe_hnd
, mem_ctx
, sharename
,
1443 PRINTER_ALL_ACCESS
, cli
->user_name
, &hnd
))
1446 /* check for existing dst printer */
1447 if (!net_spoolss_getprinter(pipe_hnd
, mem_ctx
, &hnd
, level
, &info
))
1450 if (!info
.info7
.guid
) {
1453 state
= info
.info7
.action
;
1455 case DSPRINT_PUBLISH
:
1456 printf(_("printer [%s] is published"),
1459 printf(_(", guid: %s"),info
.info7
.guid
);
1462 case DSPRINT_UNPUBLISH
:
1463 printf(_("printer [%s] is unpublished\n"),
1466 case DSPRINT_UPDATE
:
1467 printf(_("printer [%s] is currently updating\n"),
1471 printf(_("unkown state: %d\n"), state
);
1476 nt_status
= NT_STATUS_OK
;
1479 if (is_valid_policy_hnd(&hnd
))
1480 rpccli_spoolss_ClosePrinter(pipe_hnd
, mem_ctx
, &hnd
, NULL
);
1486 * Migrate Printer-ACLs from a source server to the destination server
1488 * All parameters are provided by the run_rpc_command function, except for
1489 * argc, argv which are passed through.
1491 * @param c A net_context structure
1492 * @param domain_sid The domain sid aquired from the remote server
1493 * @param cli A cli_state connected to the server.
1494 * @param mem_ctx Talloc context, destoyed on compleation of the function.
1495 * @param argc Standard main() style argc
1496 * @param argv Standard main() style argv. Initial components are already
1499 * @return Normal NTSTATUS return.
1502 NTSTATUS
rpc_printer_migrate_security_internals(struct net_context
*c
,
1503 const struct dom_sid
*domain_sid
,
1504 const char *domain_name
,
1505 struct cli_state
*cli
,
1506 struct rpc_pipe_client
*pipe_hnd
,
1507 TALLOC_CTX
*mem_ctx
,
1511 /* TODO: what now, info2 or info3 ?
1512 convince jerry that we should add clientside setacls level 3 at least
1514 NTSTATUS nt_status
= NT_STATUS_UNSUCCESSFUL
;
1516 uint32_t num_printers
;
1518 const char *printername
, *sharename
;
1519 struct rpc_pipe_client
*pipe_hnd_dst
= NULL
;
1520 struct policy_handle hnd_src
, hnd_dst
;
1521 union spoolss_PrinterInfo
*info_enum
;
1522 struct cli_state
*cli_dst
= NULL
;
1523 union spoolss_PrinterInfo info_src
, info_dst
;
1525 DEBUG(3,("copying printer ACLs\n"));
1527 /* connect destination PI_SPOOLSS */
1528 nt_status
= connect_dst_pipe(c
, &cli_dst
, &pipe_hnd_dst
,
1529 &ndr_table_spoolss
.syntax_id
);
1530 if (!NT_STATUS_IS_OK(nt_status
))
1534 /* enum source printers */
1535 if (!get_printer_info(pipe_hnd
, mem_ctx
, level
, argc
, argv
, &num_printers
, &info_enum
)) {
1536 nt_status
= NT_STATUS_UNSUCCESSFUL
;
1540 if (!num_printers
) {
1541 printf (_("no printers found on server.\n"));
1542 nt_status
= NT_STATUS_OK
;
1546 /* do something for all printers */
1547 for (i
= 0; i
< num_printers
; i
++) {
1549 /* do some initialization */
1550 printername
= info_enum
[i
].info2
.printername
;
1551 sharename
= info_enum
[i
].info2
.sharename
;
1553 if (!printername
|| !sharename
) {
1554 nt_status
= NT_STATUS_UNSUCCESSFUL
;
1558 /* we can reset NT_STATUS here because we do not
1559 get any real NT_STATUS-codes anymore from now on */
1560 nt_status
= NT_STATUS_UNSUCCESSFUL
;
1562 d_printf(_("migrating printer ACLs for: [%s] / [%s]\n"),
1563 printername
, sharename
);
1565 /* according to msdn you have specify these access-rights
1566 to see the security descriptor
1567 - READ_CONTROL (DACL)
1568 - ACCESS_SYSTEM_SECURITY (SACL)
1571 /* open src printer handle */
1572 if (!net_spoolss_open_printer_ex(pipe_hnd
, mem_ctx
, sharename
,
1573 MAXIMUM_ALLOWED_ACCESS
, cli
->user_name
, &hnd_src
))
1576 /* open dst printer handle */
1577 if (!net_spoolss_open_printer_ex(pipe_hnd_dst
, mem_ctx
, sharename
,
1578 PRINTER_ALL_ACCESS
, cli_dst
->user_name
, &hnd_dst
))
1581 /* check for existing dst printer */
1582 if (!net_spoolss_getprinter(pipe_hnd_dst
, mem_ctx
, &hnd_dst
, level
, &info_dst
))
1585 /* check for existing src printer */
1586 if (!net_spoolss_getprinter(pipe_hnd
, mem_ctx
, &hnd_src
, 3, &info_src
))
1589 /* Copy Security Descriptor */
1591 /* copy secdesc (info level 2) */
1592 info_dst
.info2
.devmode
= NULL
;
1593 info_dst
.info2
.secdesc
= dup_sec_desc(mem_ctx
, info_src
.info3
.secdesc
);
1596 display_sec_desc(info_dst
.info2
.secdesc
);
1598 if (!net_spoolss_setprinter(pipe_hnd_dst
, mem_ctx
, &hnd_dst
, 2, &info_dst
))
1601 DEBUGADD(1,("\tSetPrinter of SECDESC succeeded\n"));
1604 /* close printer handles here */
1605 if (is_valid_policy_hnd(&hnd_src
)) {
1606 rpccli_spoolss_ClosePrinter(pipe_hnd
, mem_ctx
, &hnd_src
, NULL
);
1609 if (is_valid_policy_hnd(&hnd_dst
)) {
1610 rpccli_spoolss_ClosePrinter(pipe_hnd_dst
, mem_ctx
, &hnd_dst
, NULL
);
1615 nt_status
= NT_STATUS_OK
;
1619 if (is_valid_policy_hnd(&hnd_src
)) {
1620 rpccli_spoolss_ClosePrinter(pipe_hnd
, mem_ctx
, &hnd_src
, NULL
);
1623 if (is_valid_policy_hnd(&hnd_dst
)) {
1624 rpccli_spoolss_ClosePrinter(pipe_hnd_dst
, mem_ctx
, &hnd_dst
, NULL
);
1628 cli_shutdown(cli_dst
);
1634 * Migrate printer-forms from a src server to the dst server
1636 * All parameters are provided by the run_rpc_command function, except for
1637 * argc, argv which are passed through.
1639 * @param c A net_context structure
1640 * @param domain_sid The domain sid aquired from the remote server
1641 * @param cli A cli_state connected to the server.
1642 * @param mem_ctx Talloc context, destoyed on compleation of the function.
1643 * @param argc Standard main() style argc
1644 * @param argv Standard main() style argv. Initial components are already
1647 * @return Normal NTSTATUS return.
1650 NTSTATUS
rpc_printer_migrate_forms_internals(struct net_context
*c
,
1651 const struct dom_sid
*domain_sid
,
1652 const char *domain_name
,
1653 struct cli_state
*cli
,
1654 struct rpc_pipe_client
*pipe_hnd
,
1655 TALLOC_CTX
*mem_ctx
,
1659 NTSTATUS nt_status
= NT_STATUS_UNSUCCESSFUL
;
1662 uint32_t num_printers
;
1664 const char *printername
, *sharename
;
1665 struct rpc_pipe_client
*pipe_hnd_dst
= NULL
;
1666 struct policy_handle hnd_src
, hnd_dst
;
1667 union spoolss_PrinterInfo
*info_enum
;
1668 union spoolss_PrinterInfo info_dst
;
1670 union spoolss_FormInfo
*forms
;
1671 struct cli_state
*cli_dst
= NULL
;
1673 DEBUG(3,("copying forms\n"));
1675 /* connect destination PI_SPOOLSS */
1676 nt_status
= connect_dst_pipe(c
, &cli_dst
, &pipe_hnd_dst
,
1677 &ndr_table_spoolss
.syntax_id
);
1678 if (!NT_STATUS_IS_OK(nt_status
))
1681 /* enum src printers */
1682 if (!get_printer_info(pipe_hnd
, mem_ctx
, 2, argc
, argv
, &num_printers
, &info_enum
)) {
1683 nt_status
= NT_STATUS_UNSUCCESSFUL
;
1687 if (!num_printers
) {
1688 printf (_("no printers found on server.\n"));
1689 nt_status
= NT_STATUS_OK
;
1693 /* do something for all printers */
1694 for (i
= 0; i
< num_printers
; i
++) {
1696 /* do some initialization */
1697 printername
= info_enum
[i
].info2
.printername
;
1698 sharename
= info_enum
[i
].info2
.sharename
;
1700 if (!printername
|| !sharename
) {
1701 nt_status
= NT_STATUS_UNSUCCESSFUL
;
1704 /* we can reset NT_STATUS here because we do not
1705 get any real NT_STATUS-codes anymore from now on */
1706 nt_status
= NT_STATUS_UNSUCCESSFUL
;
1708 d_printf(_("migrating printer forms for: [%s] / [%s]\n"),
1709 printername
, sharename
);
1712 /* open src printer handle */
1713 if (!net_spoolss_open_printer_ex(pipe_hnd
, mem_ctx
, sharename
,
1714 MAXIMUM_ALLOWED_ACCESS
, cli
->user_name
, &hnd_src
))
1717 /* open dst printer handle */
1718 if (!net_spoolss_open_printer_ex(pipe_hnd_dst
, mem_ctx
, sharename
,
1719 PRINTER_ALL_ACCESS
, cli
->user_name
, &hnd_dst
))
1722 /* check for existing dst printer */
1723 if (!net_spoolss_getprinter(pipe_hnd_dst
, mem_ctx
, &hnd_dst
, level
, &info_dst
))
1726 /* finally migrate forms */
1727 if (!net_spoolss_enumforms(pipe_hnd
, mem_ctx
, &hnd_src
, level
, &num_forms
, &forms
))
1730 DEBUG(1,("got %d forms for printer\n", num_forms
));
1733 for (f
= 0; f
< num_forms
; f
++) {
1735 union spoolss_AddFormInfo info
;
1738 /* only migrate FORM_PRINTER types, according to jerry
1739 FORM_BUILTIN-types are hard-coded in samba */
1740 if (forms
[f
].info1
.flags
!= SPOOLSS_FORM_PRINTER
)
1744 d_printf(_("\tmigrating form # %d [%s] of type "
1746 f
, forms
[f
].info1
.form_name
,
1747 forms
[f
].info1
.flags
);
1749 info
.info1
= (struct spoolss_AddFormInfo1
*)
1750 (void *)&forms
[f
].info1
;
1752 /* FIXME: there might be something wrong with samba's
1754 status
= rpccli_spoolss_AddForm(pipe_hnd_dst
, mem_ctx
,
1759 if (!W_ERROR_IS_OK(result
)) {
1760 d_printf(_("\tAddForm form %d: [%s] refused.\n"),
1761 f
, forms
[f
].info1
.form_name
);
1765 DEBUGADD(1,("\tAddForm of [%s] succeeded\n",
1766 forms
[f
].info1
.form_name
));
1770 /* close printer handles here */
1771 if (is_valid_policy_hnd(&hnd_src
)) {
1772 rpccli_spoolss_ClosePrinter(pipe_hnd
, mem_ctx
, &hnd_src
, NULL
);
1775 if (is_valid_policy_hnd(&hnd_dst
)) {
1776 rpccli_spoolss_ClosePrinter(pipe_hnd_dst
, mem_ctx
, &hnd_dst
, NULL
);
1780 nt_status
= NT_STATUS_OK
;
1784 if (is_valid_policy_hnd(&hnd_src
))
1785 rpccli_spoolss_ClosePrinter(pipe_hnd
, mem_ctx
, &hnd_src
, NULL
);
1787 if (is_valid_policy_hnd(&hnd_dst
))
1788 rpccli_spoolss_ClosePrinter(pipe_hnd_dst
, mem_ctx
, &hnd_dst
, NULL
);
1791 cli_shutdown(cli_dst
);
1797 * Migrate printer-drivers from a src server to the dst server
1799 * All parameters are provided by the run_rpc_command function, except for
1800 * argc, argv which are passed through.
1802 * @param c A net_context structure
1803 * @param domain_sid The domain sid aquired from the remote server
1804 * @param cli A cli_state connected to the server.
1805 * @param mem_ctx Talloc context, destoyed on compleation of the function.
1806 * @param argc Standard main() style argc
1807 * @param argv Standard main() style argv. Initial components are already
1810 * @return Normal NTSTATUS return.
1813 NTSTATUS
rpc_printer_migrate_drivers_internals(struct net_context
*c
,
1814 const struct dom_sid
*domain_sid
,
1815 const char *domain_name
,
1816 struct cli_state
*cli
,
1817 struct rpc_pipe_client
*pipe_hnd
,
1818 TALLOC_CTX
*mem_ctx
,
1822 NTSTATUS nt_status
= NT_STATUS_UNSUCCESSFUL
;
1824 uint32_t num_printers
;
1826 const char *printername
, *sharename
;
1827 bool got_src_driver_share
= false;
1828 bool got_dst_driver_share
= false;
1829 struct rpc_pipe_client
*pipe_hnd_dst
= NULL
;
1830 struct policy_handle hnd_src
, hnd_dst
;
1831 union spoolss_DriverInfo drv_info_src
;
1832 union spoolss_PrinterInfo
*info_enum
;
1833 union spoolss_PrinterInfo info_dst
;
1834 struct cli_state
*cli_dst
= NULL
;
1835 struct cli_state
*cli_share_src
= NULL
;
1836 struct cli_state
*cli_share_dst
= NULL
;
1837 const char *drivername
= NULL
;
1839 DEBUG(3,("copying printer-drivers\n"));
1841 nt_status
= connect_dst_pipe(c
, &cli_dst
, &pipe_hnd_dst
,
1842 &ndr_table_spoolss
.syntax_id
);
1843 if (!NT_STATUS_IS_OK(nt_status
))
1846 /* open print$-share on the src server */
1847 nt_status
= connect_to_service(c
, &cli_share_src
, &cli
->dest_ss
,
1848 cli
->desthost
, "print$", "A:");
1849 if (!NT_STATUS_IS_OK(nt_status
))
1852 got_src_driver_share
= true;
1855 /* open print$-share on the dst server */
1856 nt_status
= connect_to_service(c
, &cli_share_dst
, &cli_dst
->dest_ss
,
1857 cli_dst
->desthost
, "print$", "A:");
1858 if (!NT_STATUS_IS_OK(nt_status
))
1861 got_dst_driver_share
= true;
1864 /* enum src printers */
1865 if (!get_printer_info(pipe_hnd
, mem_ctx
, 2, argc
, argv
, &num_printers
, &info_enum
)) {
1866 nt_status
= NT_STATUS_UNSUCCESSFUL
;
1870 if (num_printers
== 0) {
1871 printf (_("no printers found on server.\n"));
1872 nt_status
= NT_STATUS_OK
;
1877 /* do something for all printers */
1878 for (p
= 0; p
< num_printers
; p
++) {
1880 /* do some initialization */
1881 printername
= info_enum
[p
].info2
.printername
;
1882 sharename
= info_enum
[p
].info2
.sharename
;
1884 if (!printername
|| !sharename
) {
1885 nt_status
= NT_STATUS_UNSUCCESSFUL
;
1889 /* we can reset NT_STATUS here because we do not
1890 get any real NT_STATUS-codes anymore from now on */
1891 nt_status
= NT_STATUS_UNSUCCESSFUL
;
1893 d_printf(_("migrating printer driver for: [%s] / [%s]\n"),
1894 printername
, sharename
);
1896 /* open dst printer handle */
1897 if (!net_spoolss_open_printer_ex(pipe_hnd_dst
, mem_ctx
, sharename
,
1898 PRINTER_ALL_ACCESS
, cli
->user_name
, &hnd_dst
))
1901 /* check for existing dst printer */
1902 if (!net_spoolss_getprinter(pipe_hnd_dst
, mem_ctx
, &hnd_dst
, 2, &info_dst
))
1906 /* open src printer handle */
1907 if (!net_spoolss_open_printer_ex(pipe_hnd
, mem_ctx
, sharename
,
1908 MAXIMUM_ALLOWED_ACCESS
,
1909 pipe_hnd
->auth
->user_name
,
1913 /* in a first step call getdriver for each shared printer (per arch)
1914 to get a list of all files that have to be copied */
1916 for (i
=0; archi_table
[i
].long_archi
!=NULL
; i
++) {
1919 if (!net_spoolss_getprinterdriver(pipe_hnd
, mem_ctx
, &hnd_src
,
1920 level
, archi_table
[i
].long_archi
,
1921 archi_table
[i
].version
, &drv_info_src
))
1924 drivername
= drv_info_src
.info3
.driver_name
;
1927 display_print_driver3(&drv_info_src
.info3
);
1929 /* check arch dir */
1930 nt_status
= check_arch_dir(cli_share_dst
, archi_table
[i
].short_archi
);
1931 if (!NT_STATUS_IS_OK(nt_status
))
1935 /* copy driver-files */
1936 nt_status
= copy_print_driver_3(c
, mem_ctx
, cli_share_src
, cli_share_dst
,
1937 archi_table
[i
].short_archi
,
1938 &drv_info_src
.info3
);
1939 if (!NT_STATUS_IS_OK(nt_status
))
1944 if (!net_spoolss_addprinterdriver(pipe_hnd_dst
, mem_ctx
, level
, &drv_info_src
)) {
1945 nt_status
= NT_STATUS_UNSUCCESSFUL
;
1949 DEBUGADD(1,("Sucessfully added driver [%s] for printer [%s]\n",
1950 drivername
, printername
));
1954 if (!drivername
|| strlen(drivername
) == 0) {
1955 DEBUGADD(1,("Did not get driver for printer %s\n",
1961 info_dst
.info2
.drivername
= drivername
;
1963 if (!net_spoolss_setprinter(pipe_hnd_dst
, mem_ctx
, &hnd_dst
, 2, &info_dst
)) {
1964 nt_status
= NT_STATUS_UNSUCCESSFUL
;
1968 DEBUGADD(1,("Sucessfully set driver %s for printer %s\n",
1969 drivername
, printername
));
1972 if (is_valid_policy_hnd(&hnd_dst
)) {
1973 rpccli_spoolss_ClosePrinter(pipe_hnd_dst
, mem_ctx
, &hnd_dst
, NULL
);
1977 if (is_valid_policy_hnd(&hnd_src
)) {
1978 rpccli_spoolss_ClosePrinter(pipe_hnd
, mem_ctx
, &hnd_src
, NULL
);
1982 nt_status
= NT_STATUS_OK
;
1986 if (is_valid_policy_hnd(&hnd_src
))
1987 rpccli_spoolss_ClosePrinter(pipe_hnd
, mem_ctx
, &hnd_src
, NULL
);
1989 if (is_valid_policy_hnd(&hnd_dst
))
1990 rpccli_spoolss_ClosePrinter(pipe_hnd_dst
, mem_ctx
, &hnd_dst
, NULL
);
1993 cli_shutdown(cli_dst
);
1996 if (got_src_driver_share
)
1997 cli_shutdown(cli_share_src
);
1999 if (got_dst_driver_share
)
2000 cli_shutdown(cli_share_dst
);
2007 * Migrate printer-queues from a src to the dst server
2008 * (requires a working "addprinter command" to be installed for the local smbd)
2010 * All parameters are provided by the run_rpc_command function, except for
2011 * argc, argv which are passed through.
2013 * @param c A net_context structure
2014 * @param domain_sid The domain sid aquired from the remote server
2015 * @param cli A cli_state connected to the server.
2016 * @param mem_ctx Talloc context, destoyed on compleation of the function.
2017 * @param argc Standard main() style argc
2018 * @param argv Standard main() style argv. Initial components are already
2021 * @return Normal NTSTATUS return.
2024 NTSTATUS
rpc_printer_migrate_printers_internals(struct net_context
*c
,
2025 const struct dom_sid
*domain_sid
,
2026 const char *domain_name
,
2027 struct cli_state
*cli
,
2028 struct rpc_pipe_client
*pipe_hnd
,
2029 TALLOC_CTX
*mem_ctx
,
2034 NTSTATUS nt_status
= NT_STATUS_UNSUCCESSFUL
;
2035 uint32_t i
= 0, num_printers
;
2037 union spoolss_PrinterInfo info_dst
, info_src
;
2038 union spoolss_PrinterInfo
*info_enum
;
2039 struct cli_state
*cli_dst
= NULL
;
2040 struct policy_handle hnd_dst
, hnd_src
;
2041 const char *printername
, *sharename
;
2042 struct rpc_pipe_client
*pipe_hnd_dst
= NULL
;
2043 struct spoolss_SetPrinterInfoCtr info_ctr
;
2045 DEBUG(3,("copying printers\n"));
2047 /* connect destination PI_SPOOLSS */
2048 nt_status
= connect_dst_pipe(c
, &cli_dst
, &pipe_hnd_dst
,
2049 &ndr_table_spoolss
.syntax_id
);
2050 if (!NT_STATUS_IS_OK(nt_status
))
2054 if (!get_printer_info(pipe_hnd
, mem_ctx
, level
, argc
, argv
, &num_printers
, &info_enum
)) {
2055 nt_status
= NT_STATUS_UNSUCCESSFUL
;
2059 if (!num_printers
) {
2060 printf (_("no printers found on server.\n"));
2061 nt_status
= NT_STATUS_OK
;
2065 /* do something for all printers */
2066 for (i
= 0; i
< num_printers
; i
++) {
2068 struct spoolss_SetPrinterInfo2 info2
;
2070 /* do some initialization */
2071 printername
= info_enum
[i
].info2
.printername
;
2072 sharename
= info_enum
[i
].info2
.sharename
;
2074 if (!printername
|| !sharename
) {
2075 nt_status
= NT_STATUS_UNSUCCESSFUL
;
2078 /* we can reset NT_STATUS here because we do not
2079 get any real NT_STATUS-codes anymore from now on */
2080 nt_status
= NT_STATUS_UNSUCCESSFUL
;
2082 d_printf(_("migrating printer queue for: [%s] / [%s]\n"),
2083 printername
, sharename
);
2085 /* open dst printer handle */
2086 if (!net_spoolss_open_printer_ex(pipe_hnd_dst
, mem_ctx
, sharename
,
2087 PRINTER_ALL_ACCESS
, cli
->user_name
, &hnd_dst
)) {
2089 DEBUG(1,("could not open printer: %s\n", sharename
));
2092 /* check for existing dst printer */
2093 if (!net_spoolss_getprinter(pipe_hnd_dst
, mem_ctx
, &hnd_dst
, level
, &info_dst
)) {
2094 printf (_("could not get printer, creating printer.\n"));
2096 DEBUG(1,("printer already exists: %s\n", sharename
));
2097 /* close printer handle here - dst only, not got src yet. */
2098 if (is_valid_policy_hnd(&hnd_dst
)) {
2099 rpccli_spoolss_ClosePrinter(pipe_hnd_dst
, mem_ctx
, &hnd_dst
, NULL
);
2104 /* now get again src printer ctr via getprinter,
2105 we first need a handle for that */
2107 /* open src printer handle */
2108 if (!net_spoolss_open_printer_ex(pipe_hnd
, mem_ctx
, sharename
,
2109 MAXIMUM_ALLOWED_ACCESS
, cli
->user_name
, &hnd_src
))
2112 /* getprinter on the src server */
2113 if (!net_spoolss_getprinter(pipe_hnd
, mem_ctx
, &hnd_src
, level
, &info_src
))
2116 /* copy each src printer to a dst printer 1:1,
2117 maybe some values have to be changed though */
2118 d_printf(_("creating printer: %s\n"), printername
);
2120 info_ctr
.level
= level
;
2121 spoolss_printerinfo2_to_setprinterinfo2(&info_src
.info2
, &info2
);
2122 info_ctr
.info
.info2
= &info2
;
2124 result
= rpccli_spoolss_addprinterex(pipe_hnd_dst
,
2128 if (W_ERROR_IS_OK(result
))
2129 d_printf (_("printer [%s] successfully added.\n"),
2131 else if (W_ERROR_V(result
) == W_ERROR_V(WERR_PRINTER_ALREADY_EXISTS
))
2132 d_fprintf (stderr
, _("printer [%s] already exists.\n"),
2135 d_fprintf (stderr
, _("could not create printer [%s]\n"),
2140 /* close printer handles here */
2141 if (is_valid_policy_hnd(&hnd_src
)) {
2142 rpccli_spoolss_ClosePrinter(pipe_hnd
, mem_ctx
, &hnd_src
, NULL
);
2145 if (is_valid_policy_hnd(&hnd_dst
)) {
2146 rpccli_spoolss_ClosePrinter(pipe_hnd_dst
, mem_ctx
, &hnd_dst
, NULL
);
2150 nt_status
= NT_STATUS_OK
;
2153 if (is_valid_policy_hnd(&hnd_src
))
2154 rpccli_spoolss_ClosePrinter(pipe_hnd
, mem_ctx
, &hnd_src
, NULL
);
2156 if (is_valid_policy_hnd(&hnd_dst
))
2157 rpccli_spoolss_ClosePrinter(pipe_hnd_dst
, mem_ctx
, &hnd_dst
, NULL
);
2160 cli_shutdown(cli_dst
);
2166 * Migrate Printer-Settings from a src server to the dst server
2167 * (for this to work, printers and drivers already have to be migrated earlier)
2169 * All parameters are provided by the run_rpc_command function, except for
2170 * argc, argv which are passed through.
2172 * @param c A net_context structure
2173 * @param domain_sid The domain sid aquired from the remote server
2174 * @param cli A cli_state connected to the server.
2175 * @param mem_ctx Talloc context, destoyed on compleation of the function.
2176 * @param argc Standard main() style argc
2177 * @param argv Standard main() style argv. Initial components are already
2180 * @return Normal NTSTATUS return.
2183 NTSTATUS
rpc_printer_migrate_settings_internals(struct net_context
*c
,
2184 const struct dom_sid
*domain_sid
,
2185 const char *domain_name
,
2186 struct cli_state
*cli
,
2187 struct rpc_pipe_client
*pipe_hnd
,
2188 TALLOC_CTX
*mem_ctx
,
2193 /* FIXME: Here the nightmare begins */
2196 NTSTATUS nt_status
= NT_STATUS_UNSUCCESSFUL
;
2197 uint32_t i
= 0, p
= 0, j
= 0;
2198 uint32_t num_printers
;
2200 const char *printername
, *sharename
;
2201 struct rpc_pipe_client
*pipe_hnd_dst
= NULL
;
2202 struct policy_handle hnd_src
, hnd_dst
;
2203 union spoolss_PrinterInfo
*info_enum
;
2204 union spoolss_PrinterInfo info_dst_publish
;
2205 union spoolss_PrinterInfo info_dst
;
2206 struct cli_state
*cli_dst
= NULL
;
2207 char *devicename
= NULL
, *unc_name
= NULL
, *url
= NULL
;
2208 const char *longname
;
2209 const char **keylist
= NULL
;
2212 ZERO_STRUCT(info_dst_publish
);
2214 DEBUG(3,("copying printer settings\n"));
2216 /* connect destination PI_SPOOLSS */
2217 nt_status
= connect_dst_pipe(c
, &cli_dst
, &pipe_hnd_dst
,
2218 &ndr_table_spoolss
.syntax_id
);
2219 if (!NT_STATUS_IS_OK(nt_status
))
2222 /* enum src printers */
2223 if (!get_printer_info(pipe_hnd
, mem_ctx
, level
, argc
, argv
, &num_printers
, &info_enum
)) {
2224 nt_status
= NT_STATUS_UNSUCCESSFUL
;
2228 if (!num_printers
) {
2229 printf (_("no printers found on server.\n"));
2230 nt_status
= NT_STATUS_OK
;
2235 /* needed for dns-strings in regkeys */
2236 longname
= get_mydnsfullname();
2238 nt_status
= NT_STATUS_UNSUCCESSFUL
;
2242 /* do something for all printers */
2243 for (i
= 0; i
< num_printers
; i
++) {
2245 uint32_t value_offered
= 0, value_needed
;
2246 uint32_t data_offered
= 0, data_needed
;
2247 enum winreg_Type type
;
2248 uint8_t *buffer
= NULL
;
2249 const char *value_name
= NULL
;
2251 /* do some initialization */
2252 printername
= info_enum
[i
].info2
.printername
;
2253 sharename
= info_enum
[i
].info2
.sharename
;
2255 if (!printername
|| !sharename
) {
2256 nt_status
= NT_STATUS_UNSUCCESSFUL
;
2259 /* we can reset NT_STATUS here because we do not
2260 get any real NT_STATUS-codes anymore from now on */
2261 nt_status
= NT_STATUS_UNSUCCESSFUL
;
2263 d_printf(_("migrating printer settings for: [%s] / [%s]\n"),
2264 printername
, sharename
);
2267 /* open src printer handle */
2268 if (!net_spoolss_open_printer_ex(pipe_hnd
, mem_ctx
, sharename
,
2269 MAXIMUM_ALLOWED_ACCESS
, cli
->user_name
, &hnd_src
))
2272 /* open dst printer handle */
2273 if (!net_spoolss_open_printer_ex(pipe_hnd_dst
, mem_ctx
, sharename
,
2274 PRINTER_ALL_ACCESS
, cli_dst
->user_name
, &hnd_dst
))
2277 /* check for existing dst printer */
2278 if (!net_spoolss_getprinter(pipe_hnd_dst
, mem_ctx
, &hnd_dst
,
2283 /* STEP 1: COPY DEVICE-MODE and other
2284 PRINTER_INFO_2-attributes
2287 info_dst
.info2
= info_enum
[i
].info2
;
2289 /* why is the port always disconnected when the printer
2290 is correctly installed (incl. driver ???) */
2291 info_dst
.info2
.portname
= SAMBA_PRINTER_PORT_NAME
;
2293 /* check if printer is published */
2294 if (info_enum
[i
].info2
.attributes
& PRINTER_ATTRIBUTE_PUBLISHED
) {
2296 /* check for existing dst printer */
2297 if (!net_spoolss_getprinter(pipe_hnd_dst
, mem_ctx
, &hnd_dst
, 7, &info_dst_publish
))
2300 info_dst_publish
.info7
.action
= DSPRINT_PUBLISH
;
2302 /* ignore false from setprinter due to WERR_IO_PENDING */
2303 net_spoolss_setprinter(pipe_hnd_dst
, mem_ctx
, &hnd_dst
, 7, &info_dst_publish
);
2305 DEBUG(3,("republished printer\n"));
2308 if (info_enum
[i
].info2
.devmode
!= NULL
) {
2310 /* copy devmode (info level 2) */
2311 info_dst
.info2
.devmode
= info_enum
[i
].info2
.devmode
;
2313 /* do not copy security descriptor (we have another
2314 * command for that) */
2315 info_dst
.info2
.secdesc
= NULL
;
2318 info_dst
.info2
.devmode
.devicename
=
2319 talloc_asprintf(mem_ctx
, "\\\\%s\\%s",
2320 longname
, printername
);
2321 if (!info_dst
.info2
.devmode
.devicename
) {
2322 nt_status
= NT_STATUS_NO_MEMORY
;
2326 if (!net_spoolss_setprinter(pipe_hnd_dst
, mem_ctx
, &hnd_dst
,
2330 DEBUGADD(1,("\tSetPrinter of DEVICEMODE succeeded\n"));
2333 /* STEP 2: COPY REGISTRY VALUES */
2335 /* please keep in mind that samba parse_spools gives horribly
2336 crippled results when used to rpccli_spoolss_enumprinterdataex
2337 a win2k3-server. (Bugzilla #1851)
2338 FIXME: IIRC I've seen it too on a win2k-server
2341 /* enumerate data on src handle */
2342 nt_status
= rpccli_spoolss_EnumPrinterData(pipe_hnd
, mem_ctx
,
2354 data_offered
= data_needed
;
2355 value_offered
= value_needed
;
2356 buffer
= talloc_zero_array(mem_ctx
, uint8_t, data_needed
);
2357 value_name
= talloc_zero_array(mem_ctx
, char, value_needed
);
2359 /* loop for all printerdata of "PrinterDriverData" */
2360 while (NT_STATUS_IS_OK(nt_status
) && W_ERROR_IS_OK(result
)) {
2362 nt_status
= rpccli_spoolss_EnumPrinterData(pipe_hnd
, mem_ctx
,
2373 /* loop for all reg_keys */
2374 if (NT_STATUS_IS_OK(nt_status
) && W_ERROR_IS_OK(result
)) {
2377 if (c
->opt_verbose
) {
2378 struct regval_blob
*v
;
2380 v
= regval_compose(talloc_tos(),
2386 nt_status
= NT_STATUS_NO_MEMORY
;
2390 display_reg_value(SPOOL_PRINTERDATA_KEY
, v
);
2395 if (!net_spoolss_setprinterdata(pipe_hnd_dst
, mem_ctx
,
2396 &hnd_dst
, value_name
,
2397 type
, buffer
, data_offered
))
2400 DEBUGADD(1,("\tSetPrinterData of [%s] succeeded\n",
2405 /* STEP 3: COPY SUBKEY VALUES */
2407 /* here we need to enum all printer_keys and then work
2408 on the result with enum_printer_key_ex. nt4 does not
2409 respond to enumprinterkey, win2k does, so continue
2410 in case of an error */
2412 if (!net_spoolss_enumprinterkey(pipe_hnd
, mem_ctx
, &hnd_src
, "", &keylist
)) {
2413 printf(_("got no key-data\n"));
2418 /* work on a list of printer keys
2419 each key has to be enumerated to get all required
2420 information. information is then set via setprinterdataex-calls */
2422 if (keylist
== NULL
)
2425 for (i
=0; keylist
&& keylist
[i
] != NULL
; i
++) {
2427 const char *subkey
= keylist
[i
];
2429 struct spoolss_PrinterEnumValues
*info
;
2431 /* enumerate all src subkeys */
2432 if (!net_spoolss_enumprinterdataex(pipe_hnd
, mem_ctx
, 0,
2438 for (j
=0; j
< count
; j
++) {
2440 struct regval_blob
*value
;
2445 /* although samba replies with sane data in most cases we
2446 should try to avoid writing wrong registry data */
2448 if (strequal(info
[j
].value_name
, SPOOL_REG_PORTNAME
) ||
2449 strequal(info
[j
].value_name
, SPOOL_REG_UNCNAME
) ||
2450 strequal(info
[j
].value_name
, SPOOL_REG_URL
) ||
2451 strequal(info
[j
].value_name
, SPOOL_REG_SHORTSERVERNAME
) ||
2452 strequal(info
[j
].value_name
, SPOOL_REG_SERVERNAME
)) {
2454 if (strequal(info
[j
].value_name
, SPOOL_REG_PORTNAME
)) {
2456 /* although windows uses a multi-sz, we use a sz */
2457 push_reg_sz(mem_ctx
, &blob
, SAMBA_PRINTER_PORT_NAME
);
2460 if (strequal(info
[j
].value_name
, SPOOL_REG_UNCNAME
)) {
2462 if (asprintf(&unc_name
, "\\\\%s\\%s", longname
, sharename
) < 0) {
2463 nt_status
= NT_STATUS_NO_MEMORY
;
2466 push_reg_sz(mem_ctx
, &blob
, unc_name
);
2469 if (strequal(info
[j
].value_name
, SPOOL_REG_URL
)) {
2474 /* FIXME: should we really do that ??? */
2475 if (asprintf(&url
, "http://%s:631/printers/%s", longname
, sharename
) < 0) {
2476 nt_status
= NT_STATUS_NO_MEMORY
;
2479 push_reg_sz(mem_ctx
, NULL
, &blob
, url
);
2480 fstrcpy(value
.valuename
, SPOOL_REG_URL
);
2484 if (strequal(info
[j
].value_name
, SPOOL_REG_SERVERNAME
)) {
2486 push_reg_sz(mem_ctx
, &blob
, longname
);
2489 if (strequal(info
[j
].value_name
, SPOOL_REG_SHORTSERVERNAME
)) {
2491 push_reg_sz(mem_ctx
, &blob
, global_myname());
2494 value
= regval_compose(talloc_tos(),
2497 blob
.length
== 0 ? NULL
: blob
.data
,
2499 if (value
== NULL
) {
2500 nt_status
= NT_STATUS_NO_MEMORY
;
2505 display_reg_value(subkey
, value
);
2507 /* here we have to set all subkeys on the dst server */
2508 if (!net_spoolss_setprinterdataex(pipe_hnd_dst
, mem_ctx
, &hnd_dst
,
2518 struct regval_blob
*v
;
2520 v
= regval_compose(talloc_tos(),
2524 info
[j
].data
->length
);
2526 nt_status
= NT_STATUS_NO_MEMORY
;
2530 if (c
->opt_verbose
) {
2531 display_reg_value(subkey
, v
);
2534 /* here we have to set all subkeys on the dst server */
2535 if (!net_spoolss_setprinterdataex(pipe_hnd_dst
, mem_ctx
, &hnd_dst
,
2543 DEBUGADD(1,("\tSetPrinterDataEx of key [%s\\%s] succeeded\n",
2544 subkey
, info
[j
].value_name
));
2549 TALLOC_FREE(keylist
);
2551 /* close printer handles here */
2552 if (is_valid_policy_hnd(&hnd_src
)) {
2553 rpccli_spoolss_ClosePrinter(pipe_hnd
, mem_ctx
, &hnd_src
, NULL
);
2556 if (is_valid_policy_hnd(&hnd_dst
)) {
2557 rpccli_spoolss_ClosePrinter(pipe_hnd_dst
, mem_ctx
, &hnd_dst
, NULL
);
2562 nt_status
= NT_STATUS_OK
;
2565 SAFE_FREE(devicename
);
2567 SAFE_FREE(unc_name
);
2569 if (is_valid_policy_hnd(&hnd_src
))
2570 rpccli_spoolss_ClosePrinter(pipe_hnd
, mem_ctx
, &hnd_src
, NULL
);
2572 if (is_valid_policy_hnd(&hnd_dst
))
2573 rpccli_spoolss_ClosePrinter(pipe_hnd_dst
, mem_ctx
, &hnd_dst
, NULL
);
2576 cli_shutdown(cli_dst
);