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"
22 /* support itanium as well */
23 static const struct print_architecture_table_node archi_table[]= {
25 {"Windows 4.0", "WIN40", 0 },
26 {"Windows NT x86", "W32X86", 2 },
27 {"Windows NT x86", "W32X86", 3 },
28 {"Windows NT R4000", "W32MIPS", 2 },
29 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
30 {"Windows NT PowerPC", "W32PPC", 2 },
31 {"Windows IA64", "IA64", 3 },
32 {"Windows x64", "x64", 3 },
38 * This display-printdriver-functions was borrowed from rpcclient/cmd_spoolss.c.
39 * It is here for debugging purpose and should be removed later on.
42 /****************************************************************************
43 Printer info level 3 display function.
44 ****************************************************************************/
46 static void display_print_driver3(struct spoolss_DriverInfo3 *r)
54 printf("Printer Driver Info 3:\n");
55 printf("\tVersion: [%x]\n", r->version);
56 printf("\tDriver Name: [%s]\n", r->driver_name);
57 printf("\tArchitecture: [%s]\n", r->architecture);
58 printf("\tDriver Path: [%s]\n", r->driver_path);
59 printf("\tDatafile: [%s]\n", r->data_file);
60 printf("\tConfigfile: [%s]\n\n", r->config_file);
61 printf("\tHelpfile: [%s]\n\n", r->help_file);
63 for (i=0; r->dependent_files[i] != NULL; i++) {
64 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
69 printf("\tMonitorname: [%s]\n", r->monitor_name);
70 printf("\tDefaultdatatype: [%s]\n\n", r->default_datatype);
73 static void display_reg_value(const char *subkey, struct regval_blob value)
79 d_printf("\t[%s:%s]: REG_DWORD: 0x%08x\n", subkey, value.valuename,
80 *((uint32_t *) value.data_p));
84 rpcstr_pull_talloc(talloc_tos(),
92 d_printf("\t[%s:%s]: REG_SZ: %s\n", subkey, value.valuename, text);
96 d_printf("\t[%s:%s]: REG_BINARY: unknown length value not displayed\n",
97 subkey, value.valuename);
101 uint32_t i, num_values;
104 if (!W_ERROR_IS_OK(reg_pull_multi_sz(NULL, value.data_p,
105 value.size, &num_values,
107 d_printf("reg_pull_multi_sz failed\n");
111 for (i=0; i<num_values; i++) {
112 d_printf("%s\n", values[i]);
119 d_printf("\t%s: unknown type %d\n", value.valuename, value.type);
125 * Copies ACLs, DOS-attributes and timestamps from one
126 * file or directory from one connected share to another connected share
128 * @param c A net_context structure
129 * @param mem_ctx A talloc-context
130 * @param cli_share_src A connected cli_state
131 * @param cli_share_dst A connected cli_state
132 * @param src_file The source file-name
133 * @param dst_file The destination file-name
134 * @param copy_acls Whether to copy acls
135 * @param copy_attrs Whether to copy DOS attributes
136 * @param copy_timestamps Whether to preserve timestamps
137 * @param is_file Whether this file is a file or a dir
139 * @return Normal NTSTATUS return.
142 NTSTATUS net_copy_fileattr(struct net_context *c,
144 struct cli_state *cli_share_src,
145 struct cli_state *cli_share_dst,
146 const char *src_name, const char *dst_name,
147 bool copy_acls, bool copy_attrs,
148 bool copy_timestamps, bool is_file)
150 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
151 uint16_t fnum_src = 0;
152 uint16_t fnum_dst = 0;
155 time_t f_atime, f_ctime, f_mtime;
158 if (!copy_timestamps && !copy_acls && !copy_attrs)
161 /* open file/dir on the originating server */
163 DEBUGADD(3,("opening %s %s on originating server\n",
164 is_file?"file":"dir", src_name));
166 if (!NT_STATUS_IS_OK(cli_ntcreate(cli_share_src, src_name, 0, READ_CONTROL_ACCESS, 0,
167 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0x0, 0x0, &fnum_src))) {
168 DEBUGADD(0,("cannot open %s %s on originating server %s\n",
169 is_file?"file":"dir", src_name, cli_errstr(cli_share_src)));
170 nt_status = cli_nt_error(cli_share_src);
177 /* get the security descriptor */
178 sd = cli_query_secdesc(cli_share_src, fnum_src, mem_ctx);
180 DEBUG(0,("failed to get security descriptor: %s\n",
181 cli_errstr(cli_share_src)));
182 nt_status = cli_nt_error(cli_share_src);
186 if (c->opt_verbose && DEBUGLEVEL >= 3)
187 display_sec_desc(sd);
191 if (copy_attrs || copy_timestamps) {
193 /* get file attributes */
194 if (!NT_STATUS_IS_OK(cli_getattrE(cli_share_src, fnum_src, &attr, NULL,
195 &f_ctime, &f_atime, &f_mtime))) {
196 DEBUG(0,("failed to get file-attrs: %s\n",
197 cli_errstr(cli_share_src)));
198 nt_status = cli_nt_error(cli_share_src);
204 /* open the file/dir on the destination server */
206 if (!NT_STATUS_IS_OK(cli_ntcreate(cli_share_dst, dst_name, 0, WRITE_DAC_ACCESS | WRITE_OWNER_ACCESS, 0,
207 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0x0, 0x0, &fnum_dst))) {
208 DEBUG(0,("failed to open %s on the destination server: %s: %s\n",
209 is_file?"file":"dir", dst_name, cli_errstr(cli_share_dst)));
210 nt_status = cli_nt_error(cli_share_dst);
214 if (copy_timestamps) {
217 if (!NT_STATUS_IS_OK(cli_setattrE(cli_share_dst, fnum_dst, f_ctime, f_atime, f_mtime))) {
218 DEBUG(0,("failed to set file-attrs (timestamps): %s\n",
219 cli_errstr(cli_share_dst)));
220 nt_status = cli_nt_error(cli_share_dst);
228 if (!cli_set_secdesc(cli_share_dst, fnum_dst, sd)) {
229 DEBUG(0,("could not set secdesc on %s: %s\n",
230 dst_name, cli_errstr(cli_share_dst)));
231 nt_status = cli_nt_error(cli_share_dst);
239 if (!NT_STATUS_IS_OK(cli_setatr(cli_share_dst, dst_name, attr, 0))) {
240 DEBUG(0,("failed to set file-attrs: %s\n",
241 cli_errstr(cli_share_dst)));
242 nt_status = cli_nt_error(cli_share_dst);
250 if (!NT_STATUS_IS_OK(cli_close(cli_share_src, fnum_src))) {
251 d_fprintf(stderr, "could not close %s on originating server: %s\n",
252 is_file?"file":"dir", cli_errstr(cli_share_src));
253 nt_status = cli_nt_error(cli_share_src);
257 if (!NT_STATUS_IS_OK(cli_close(cli_share_dst, fnum_dst))) {
258 d_fprintf(stderr, "could not close %s on destination server: %s\n",
259 is_file?"file":"dir", cli_errstr(cli_share_dst));
260 nt_status = cli_nt_error(cli_share_dst);
265 nt_status = NT_STATUS_OK;
271 cli_close(cli_share_src, fnum_src);
274 cli_close(cli_share_dst, fnum_dst);
280 * Copy a file or directory from a connected share to another connected share
282 * @param c A net_context structure
283 * @param mem_ctx A talloc-context
284 * @param cli_share_src A connected cli_state
285 * @param cli_share_dst A connected cli_state
286 * @param src_file The source file-name
287 * @param dst_file The destination file-name
288 * @param copy_acls Whether to copy acls
289 * @param copy_attrs Whether to copy DOS attributes
290 * @param copy_timestamps Whether to preserve timestamps
291 * @param is_file Whether this file is a file or a dir
293 * @return Normal NTSTATUS return.
296 NTSTATUS net_copy_file(struct net_context *c,
298 struct cli_state *cli_share_src,
299 struct cli_state *cli_share_dst,
300 const char *src_name, const char *dst_name,
301 bool copy_acls, bool copy_attrs,
302 bool copy_timestamps, bool is_file)
304 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
305 uint16_t fnum_src = 0;
306 uint16_t fnum_dst = 0;
307 static int io_bufsize = 64512;
308 int read_size = io_bufsize;
313 if (!src_name || !dst_name)
316 if (cli_share_src == NULL || cli_share_dst == NULL)
319 /* open on the originating server */
320 DEBUGADD(3,("opening %s %s on originating server\n",
321 is_file ? "file":"dir", src_name));
323 nt_status = cli_open(cli_share_src, src_name, O_RDONLY, DENY_NONE, &fnum_src);
325 nt_status = cli_ntcreate(cli_share_src, src_name, 0, READ_CONTROL_ACCESS, 0,
326 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0x0, 0x0, &fnum_src);
328 if (!NT_STATUS_IS_OK(nt_status)) {
329 DEBUGADD(0,("cannot open %s %s on originating server %s\n",
330 is_file ? "file":"dir",
331 src_name, cli_errstr(cli_share_src)));
338 /* open file on the destination server */
339 DEBUGADD(3,("opening file %s on destination server\n", dst_name));
340 nt_status = cli_open(cli_share_dst, dst_name,
341 O_RDWR|O_CREAT|O_TRUNC, DENY_NONE, &fnum_dst);
343 if (!NT_STATUS_IS_OK(nt_status)) {
344 DEBUGADD(1,("cannot create file %s on destination server: %s\n",
345 dst_name, cli_errstr(cli_share_dst)));
349 /* allocate memory */
350 if (!(data = (char *)SMB_MALLOC(read_size))) {
351 d_fprintf(stderr, "malloc fail for size %d\n", read_size);
352 nt_status = NT_STATUS_NO_MEMORY;
359 if (c->opt_verbose) {
361 d_printf("copying [\\\\%s\\%s%s] => [\\\\%s\\%s%s] "
362 "%s ACLs and %s DOS Attributes %s\n",
363 cli_share_src->desthost, cli_share_src->share, src_name,
364 cli_share_dst->desthost, cli_share_dst->share, dst_name,
365 copy_acls ? "with" : "without",
366 copy_attrs ? "with" : "without",
367 copy_timestamps ? "(preserving timestamps)" : "" );
375 n = cli_read(cli_share_src, fnum_src, data, nread,
381 ret = cli_write(cli_share_dst, fnum_dst, 0, data,
385 d_fprintf(stderr, "Error writing file: %s\n",
386 cli_errstr(cli_share_dst));
387 nt_status = cli_nt_error(cli_share_dst);
395 if (!is_file && !NT_STATUS_IS_OK(cli_chkpath(cli_share_dst, dst_name))) {
398 DEBUGADD(3,("creating dir %s on the destination server\n",
401 if (!NT_STATUS_IS_OK(cli_mkdir(cli_share_dst, dst_name))) {
402 DEBUG(0,("cannot create directory %s: %s\n",
403 dst_name, cli_errstr(cli_share_dst)));
404 nt_status = NT_STATUS_NO_SUCH_FILE;
407 if (!NT_STATUS_IS_OK(cli_chkpath(cli_share_dst, dst_name))) {
408 d_fprintf(stderr, "cannot check for directory %s: %s\n",
409 dst_name, cli_errstr(cli_share_dst));
416 if (!NT_STATUS_IS_OK(cli_close(cli_share_src, fnum_src))) {
417 d_fprintf(stderr, "could not close file on originating server: %s\n",
418 cli_errstr(cli_share_src));
419 nt_status = cli_nt_error(cli_share_src);
423 if (is_file && !NT_STATUS_IS_OK(cli_close(cli_share_dst, fnum_dst))) {
424 d_fprintf(stderr, "could not close file on destination server: %s\n",
425 cli_errstr(cli_share_dst));
426 nt_status = cli_nt_error(cli_share_dst);
430 /* possibly we have to copy some file-attributes / acls / sd */
431 nt_status = net_copy_fileattr(c, mem_ctx, cli_share_src, cli_share_dst,
432 src_name, dst_name, copy_acls,
433 copy_attrs, copy_timestamps, is_file);
434 if (!NT_STATUS_IS_OK(nt_status))
438 nt_status = NT_STATUS_OK;
444 cli_close(cli_share_src, fnum_src);
447 cli_close(cli_share_dst, fnum_dst);
455 * Copy a driverfile from on connected share to another connected share
456 * This silently assumes that a driver-file is picked up from
458 * \\src_server\print$\{arch}\{version}\file
462 * \\dst_server\print$\{arch}\file
464 * to be added via setdriver-calls later.
465 * @param c A net_context structure
466 * @param mem_ctx A talloc-context
467 * @param cli_share_src A cli_state connected to source print$-share
468 * @param cli_share_dst A cli_state connected to destination print$-share
469 * @param file The file-name to be copied
470 * @param short_archi The name of the driver-architecture (short form)
472 * @return Normal NTSTATUS return.
475 static NTSTATUS net_copy_driverfile(struct net_context *c,
477 struct cli_state *cli_share_src,
478 struct cli_state *cli_share_dst,
479 const char *file, const char *short_archi) {
481 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
493 /* scroll through the file until we have the part
494 beyond archi_table.short_archi */
496 while (next_token_talloc(mem_ctx, &p, &tok, "\\")) {
497 if (strequal(tok, short_archi)) {
498 next_token_talloc(mem_ctx, &p, &version, "\\");
499 next_token_talloc(mem_ctx, &p, &filename, "\\");
503 /* build source file name */
504 if (asprintf(&src_name, "\\%s\\%s\\%s", short_archi, version, filename) < 0 )
505 return NT_STATUS_NO_MEMORY;
508 /* create destination file name */
509 if (asprintf(&dst_name, "\\%s\\%s", short_archi, filename) < 0 )
510 return NT_STATUS_NO_MEMORY;
513 /* finally copy the file */
514 nt_status = net_copy_file(c, mem_ctx, cli_share_src, cli_share_dst,
515 src_name, dst_name, false, false, false, true);
516 if (!NT_STATUS_IS_OK(nt_status))
519 nt_status = NT_STATUS_OK;
529 * Check for existing Architecture directory on a given server
531 * @param cli_share A cli_state connected to a print$-share
532 * @param short_archi The Architecture for the print-driver
534 * @return Normal NTSTATUS return.
537 static NTSTATUS check_arch_dir(struct cli_state *cli_share, const char *short_archi)
540 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
543 if (asprintf(&dir, "\\%s", short_archi) < 0) {
544 return NT_STATUS_NO_MEMORY;
547 DEBUG(10,("creating print-driver dir for architecture: %s\n",
550 if (!NT_STATUS_IS_OK(cli_mkdir(cli_share, dir))) {
551 DEBUG(1,("cannot create directory %s: %s\n",
552 dir, cli_errstr(cli_share)));
553 nt_status = NT_STATUS_NO_SUCH_FILE;
556 if (!NT_STATUS_IS_OK(cli_chkpath(cli_share, dir))) {
557 d_fprintf(stderr, "cannot check %s: %s\n",
558 dir, cli_errstr(cli_share));
562 nt_status = NT_STATUS_OK;
570 * Copy a print-driver (level 3) from one connected print$-share to another
571 * connected print$-share
573 * @param c A net_context structure
574 * @param mem_ctx A talloc-context
575 * @param cli_share_src A cli_state connected to a print$-share
576 * @param cli_share_dst A cli_state connected to a print$-share
577 * @param short_archi The Architecture for the print-driver
578 * @param i1 The DRIVER_INFO_3-struct
580 * @return Normal NTSTATUS return.
583 static NTSTATUS copy_print_driver_3(struct net_context *c,
585 struct cli_state *cli_share_src,
586 struct cli_state *cli_share_dst,
587 const char *short_archi,
588 struct spoolss_DriverInfo3 *r)
590 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
598 d_printf("copying driver: [%s], for architecture: [%s], version: [%d]\n",
599 r->driver_name, short_archi, r->version);
601 nt_status = net_copy_driverfile(c, mem_ctx, cli_share_src, cli_share_dst,
602 r->driver_path, short_archi);
603 if (!NT_STATUS_IS_OK(nt_status))
606 nt_status = net_copy_driverfile(c, mem_ctx, cli_share_src, cli_share_dst,
607 r->data_file, short_archi);
608 if (!NT_STATUS_IS_OK(nt_status))
611 nt_status = net_copy_driverfile(c, mem_ctx, cli_share_src, cli_share_dst,
612 r->config_file, short_archi);
613 if (!NT_STATUS_IS_OK(nt_status))
616 nt_status = net_copy_driverfile(c, mem_ctx, cli_share_src, cli_share_dst,
617 r->help_file, short_archi);
618 if (!NT_STATUS_IS_OK(nt_status))
621 for (i=0; r->dependent_files[i] != NULL; i++) {
623 nt_status = net_copy_driverfile(c, mem_ctx,
624 cli_share_src, cli_share_dst,
625 r->dependent_files[i], short_archi);
626 if (!NT_STATUS_IS_OK(nt_status)) {
635 * net_spoolss-functions
636 * =====================
638 * the net_spoolss-functions aim to simplify spoolss-client-functions
639 * required during the migration-process wrt buffer-sizes, returned
642 * this greatly reduces the complexitiy of the migrate-functions.
646 static bool net_spoolss_enum_printers(struct rpc_pipe_client *pipe_hnd,
651 uint32_t *num_printers,
652 union spoolss_PrinterInfo **info)
658 result = rpccli_spoolss_enumprinters(pipe_hnd, mem_ctx,
665 if (!W_ERROR_IS_OK(result)) {
666 printf("cannot enum printers: %s\n", win_errstr(result));
673 static bool net_spoolss_open_printer_ex(struct rpc_pipe_client *pipe_hnd,
675 const char *printername,
676 uint32_t access_required,
677 const char *username,
678 struct policy_handle *hnd)
681 fstring printername2;
683 fstrcpy(printername2, pipe_hnd->srv_name_slash);
684 fstrcat(printername2, "\\");
685 fstrcat(printername2, printername);
687 DEBUG(10,("connecting to: %s as %s for %s and access: %x\n",
688 pipe_hnd->srv_name_slash, username, printername2, access_required));
691 result = rpccli_spoolss_openprinter_ex(pipe_hnd, mem_ctx,
696 /* be more verbose */
697 if (W_ERROR_V(result) == W_ERROR_V(WERR_ACCESS_DENIED)) {
698 d_fprintf(stderr, "no access to printer [%s] on [%s] for user [%s] granted\n",
699 printername2, pipe_hnd->srv_name_slash, username);
703 if (!W_ERROR_IS_OK(result)) {
704 d_fprintf(stderr, "cannot open printer %s on server %s: %s\n",
705 printername2, pipe_hnd->srv_name_slash, win_errstr(result));
709 DEBUG(2,("got printer handle for printer: %s, server: %s\n",
710 printername2, pipe_hnd->srv_name_slash));
715 static bool net_spoolss_getprinter(struct rpc_pipe_client *pipe_hnd,
717 struct policy_handle *hnd,
719 union spoolss_PrinterInfo *info)
723 /* getprinter call */
724 result = rpccli_spoolss_getprinter(pipe_hnd, mem_ctx,
729 if (!W_ERROR_IS_OK(result)) {
730 printf("cannot get printer-info: %s\n", win_errstr(result));
737 static bool net_spoolss_setprinter(struct rpc_pipe_client *pipe_hnd,
739 struct policy_handle *hnd,
741 union spoolss_PrinterInfo *info)
745 struct spoolss_SetPrinterInfoCtr info_ctr;
746 struct spoolss_DevmodeContainer devmode_ctr;
747 struct sec_desc_buf secdesc_ctr;
749 ZERO_STRUCT(devmode_ctr);
750 ZERO_STRUCT(secdesc_ctr);
752 /* setprinter call */
754 info_ctr.level = level;
757 info_ctr.info.info0 = (struct spoolss_SetPrinterInfo0 *)
758 (void *)&info->info0;
761 info_ctr.info.info1 = (struct spoolss_SetPrinterInfo1 *)
762 (void *)&info->info1;
765 info_ctr.info.info2 = (struct spoolss_SetPrinterInfo2 *)
766 (void *)&info->info2;
769 info_ctr.info.info3 = (struct spoolss_SetPrinterInfo3 *)
770 (void *)&info->info3;
773 info_ctr.info.info4 = (struct spoolss_SetPrinterInfo4 *)
774 (void *)&info->info4;
777 info_ctr.info.info5 = (struct spoolss_SetPrinterInfo5 *)
778 (void *)&info->info5;
781 info_ctr.info.info6 = (struct spoolss_SetPrinterInfo6 *)
782 (void *)&info->info6;
785 info_ctr.info.info7 = (struct spoolss_SetPrinterInfo7 *)
786 (void *)&info->info7;
790 info_ctr.info.info8 = (struct spoolss_SetPrinterInfo8 *)
791 (void *)&info->info8;
794 info_ctr.info.info9 = (struct spoolss_SetPrinterInfo9 *)
795 (void *)&info->info9;
802 status = rpccli_spoolss_SetPrinter(pipe_hnd, mem_ctx,
810 if (!W_ERROR_IS_OK(result)) {
811 printf("cannot set printer-info: %s\n", win_errstr(result));
819 static bool net_spoolss_setprinterdata(struct rpc_pipe_client *pipe_hnd,
821 struct policy_handle *hnd,
822 const char *value_name,
823 enum winreg_Type type,
824 union spoolss_PrinterData data)
829 /* setprinterdata call */
830 status = rpccli_spoolss_SetPrinterData(pipe_hnd, mem_ctx,
835 0, /* autocalculated */
838 if (!W_ERROR_IS_OK(result)) {
839 printf ("unable to set printerdata: %s\n", win_errstr(result));
847 static bool net_spoolss_enumprinterkey(struct rpc_pipe_client *pipe_hnd,
849 struct policy_handle *hnd,
851 const char ***keylist)
855 /* enumprinterkey call */
856 result = rpccli_spoolss_enumprinterkey(pipe_hnd, mem_ctx, hnd, keyname, keylist, 0);
858 if (!W_ERROR_IS_OK(result)) {
859 printf("enumprinterkey failed: %s\n", win_errstr(result));
866 static bool net_spoolss_enumprinterdataex(struct rpc_pipe_client *pipe_hnd,
869 struct policy_handle *hnd,
872 struct spoolss_PrinterEnumValues **info)
876 /* enumprinterdataex call */
877 result = rpccli_spoolss_enumprinterdataex(pipe_hnd, mem_ctx,
884 if (!W_ERROR_IS_OK(result)) {
885 printf("enumprinterdataex failed: %s\n", win_errstr(result));
893 static bool net_spoolss_setprinterdataex(struct rpc_pipe_client *pipe_hnd,
895 struct policy_handle *hnd,
897 struct regval_blob *value)
902 /* setprinterdataex call */
903 status = rpccli_spoolss_SetPrinterDataEx(pipe_hnd, mem_ctx,
912 if (!W_ERROR_IS_OK(result)) {
913 printf("could not set printerdataex: %s\n", win_errstr(result));
920 static bool net_spoolss_enumforms(struct rpc_pipe_client *pipe_hnd,
922 struct policy_handle *hnd,
925 union spoolss_FormInfo **forms)
930 result = rpccli_spoolss_enumforms(pipe_hnd, mem_ctx,
936 if (!W_ERROR_IS_OK(result)) {
937 printf("could not enum forms: %s\n", win_errstr(result));
944 static bool net_spoolss_enumprinterdrivers (struct rpc_pipe_client *pipe_hnd,
946 uint32_t level, const char *env,
948 union spoolss_DriverInfo **info)
952 /* enumprinterdrivers call */
953 result = rpccli_spoolss_enumprinterdrivers(pipe_hnd, mem_ctx,
954 pipe_hnd->srv_name_slash,
960 if (!W_ERROR_IS_OK(result)) {
961 printf("cannot enum drivers: %s\n", win_errstr(result));
968 static bool net_spoolss_getprinterdriver(struct rpc_pipe_client *pipe_hnd,
970 struct policy_handle *hnd, uint32_t level,
971 const char *env, int version,
972 union spoolss_DriverInfo *info)
975 uint32_t server_major_version;
976 uint32_t server_minor_version;
978 /* getprinterdriver call */
979 result = rpccli_spoolss_getprinterdriver2(pipe_hnd, mem_ctx,
987 &server_major_version,
988 &server_minor_version);
989 if (!W_ERROR_IS_OK(result)) {
990 DEBUG(1,("cannot get driver (for architecture: %s): %s\n",
991 env, win_errstr(result)));
992 if (W_ERROR_V(result) != W_ERROR_V(WERR_UNKNOWN_PRINTER_DRIVER) &&
993 W_ERROR_V(result) != W_ERROR_V(WERR_INVALID_ENVIRONMENT)) {
994 printf("cannot get driver: %s\n", win_errstr(result));
1003 static bool net_spoolss_addprinterdriver(struct rpc_pipe_client *pipe_hnd,
1004 TALLOC_CTX *mem_ctx, uint32_t level,
1005 union spoolss_DriverInfo *info)
1009 struct spoolss_AddDriverInfoCtr info_ctr;
1011 info_ctr.level = level;
1015 info_ctr.info.info2 = (struct spoolss_AddDriverInfo2 *)
1016 (void *)&info->info2;
1019 info_ctr.info.info3 = (struct spoolss_AddDriverInfo3 *)
1020 (void *)&info->info3;
1023 printf("unsupported info level: %d\n", level);
1027 /* addprinterdriver call */
1028 status = rpccli_spoolss_AddPrinterDriver(pipe_hnd, mem_ctx,
1029 pipe_hnd->srv_name_slash,
1032 /* be more verbose */
1033 if (W_ERROR_V(result) == W_ERROR_V(WERR_ACCESS_DENIED)) {
1034 printf("You are not allowed to add drivers\n");
1037 if (!W_ERROR_IS_OK(result)) {
1038 printf("cannot add driver: %s\n", win_errstr(result));
1046 * abstraction function to get uint32_t num_printers and PRINTER_INFO_CTR ctr
1047 * for a single printer or for all printers depending on argc/argv
1050 static bool get_printer_info(struct rpc_pipe_client *pipe_hnd,
1051 TALLOC_CTX *mem_ctx,
1055 uint32_t *num_printers,
1056 union spoolss_PrinterInfo **info_p)
1058 struct policy_handle hnd;
1060 /* no arguments given, enumerate all printers */
1063 if (!net_spoolss_enum_printers(pipe_hnd, mem_ctx, NULL,
1064 PRINTER_ENUM_LOCAL|PRINTER_ENUM_SHARED,
1065 level, num_printers, info_p))
1071 /* argument given, get a single printer by name */
1072 if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, argv[0],
1073 MAXIMUM_ALLOWED_ACCESS,
1074 pipe_hnd->auth->user_name,
1078 if (!net_spoolss_getprinter(pipe_hnd, mem_ctx, &hnd, level, *info_p)) {
1079 rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd, NULL);
1083 rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd, NULL);
1088 DEBUG(3,("got %d printers\n", *num_printers));
1095 * List print-queues (including local printers that are not shared)
1097 * All parameters are provided by the run_rpc_command function, except for
1098 * argc, argv which are passed through.
1100 * @param c A net_context structure
1101 * @param domain_sid The domain sid aquired from the remote server
1102 * @param cli A cli_state connected to the server.
1103 * @param mem_ctx Talloc context, destoyed on compleation of the function.
1104 * @param argc Standard main() style argc
1105 * @param argv Standard main() style argv. Initial components are already
1108 * @return Normal NTSTATUS return.
1111 NTSTATUS rpc_printer_list_internals(struct net_context *c,
1112 const DOM_SID *domain_sid,
1113 const char *domain_name,
1114 struct cli_state *cli,
1115 struct rpc_pipe_client *pipe_hnd,
1116 TALLOC_CTX *mem_ctx,
1120 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1121 uint32_t i, num_printers;
1123 const char *printername, *sharename;
1124 union spoolss_PrinterInfo *info;
1126 printf("listing printers\n");
1128 if (!get_printer_info(pipe_hnd, mem_ctx, level, argc, argv, &num_printers, &info))
1131 for (i = 0; i < num_printers; i++) {
1133 /* do some initialization */
1134 printername = info[i].info2.printername;
1135 sharename = info[i].info2.sharename;
1137 if (printername && sharename) {
1138 d_printf("printer %d: %s, shared as: %s\n",
1139 i+1, printername, sharename);
1143 return NT_STATUS_OK;
1147 * List printer-drivers from a server
1149 * All parameters are provided by the run_rpc_command function, except for
1150 * argc, argv which are passed through.
1152 * @param c A net_context structure
1153 * @param domain_sid The domain sid aquired from the remote server
1154 * @param cli A cli_state connected to the server.
1155 * @param mem_ctx Talloc context, destoyed on compleation of the function.
1156 * @param argc Standard main() style argc
1157 * @param argv Standard main() style argv. Initial components are already
1160 * @return Normal NTSTATUS return.
1163 NTSTATUS rpc_printer_driver_list_internals(struct net_context *c,
1164 const DOM_SID *domain_sid,
1165 const char *domain_name,
1166 struct cli_state *cli,
1167 struct rpc_pipe_client *pipe_hnd,
1168 TALLOC_CTX *mem_ctx,
1172 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1175 union spoolss_DriverInfo *info;
1178 printf("listing printer-drivers\n");
1180 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1182 uint32_t num_drivers;
1184 /* enum remote drivers */
1185 if (!net_spoolss_enumprinterdrivers(pipe_hnd, mem_ctx, level,
1186 archi_table[i].long_archi,
1187 &num_drivers, &info)) {
1188 nt_status = NT_STATUS_UNSUCCESSFUL;
1192 if (num_drivers == 0) {
1193 d_printf ("no drivers found on server for architecture: [%s].\n",
1194 archi_table[i].long_archi);
1198 d_printf("got %d printer-drivers for architecture: [%s]\n",
1199 num_drivers, archi_table[i].long_archi);
1202 /* do something for all drivers for architecture */
1203 for (d = 0; d < num_drivers; d++) {
1204 display_print_driver3(&info[d].info3);
1208 nt_status = NT_STATUS_OK;
1216 * Publish print-queues with args-wrapper
1218 * @param cli A cli_state connected to the server.
1219 * @param mem_ctx Talloc context, destoyed on compleation of the function.
1220 * @param argc Standard main() style argc
1221 * @param argv Standard main() style argv. Initial components are already
1225 * @return Normal NTSTATUS return.
1228 static NTSTATUS rpc_printer_publish_internals_args(struct rpc_pipe_client *pipe_hnd,
1229 TALLOC_CTX *mem_ctx,
1234 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1235 uint32_t i, num_printers;
1237 const char *printername, *sharename;
1238 union spoolss_PrinterInfo *info_enum;
1239 union spoolss_PrinterInfo info;
1240 struct spoolss_SetPrinterInfoCtr info_ctr;
1241 struct spoolss_DevmodeContainer devmode_ctr;
1242 struct sec_desc_buf secdesc_ctr;
1243 struct policy_handle hnd;
1245 const char *action_str;
1247 if (!get_printer_info(pipe_hnd, mem_ctx, 2, argc, argv, &num_printers, &info_enum))
1250 for (i = 0; i < num_printers; i++) {
1252 /* do some initialization */
1253 printername = info_enum[i].info2.printername;
1254 sharename = info_enum[i].info2.sharename;
1255 if (!printername || !sharename) {
1259 /* open printer handle */
1260 if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, sharename,
1261 PRINTER_ALL_ACCESS, pipe_hnd->auth->user_name, &hnd))
1264 /* check for existing dst printer */
1265 if (!net_spoolss_getprinter(pipe_hnd, mem_ctx, &hnd, level, &info))
1268 /* check action and set string */
1270 case DSPRINT_PUBLISH:
1271 action_str = "published";
1273 case DSPRINT_UPDATE:
1274 action_str = "updated";
1276 case DSPRINT_UNPUBLISH:
1277 action_str = "unpublished";
1280 action_str = "unknown action";
1281 printf("unkown action: %d\n", action);
1285 info.info7.action = action;
1287 info_ctr.info.info7 = (struct spoolss_SetPrinterInfo7 *)
1288 (void *)&info.info7;
1290 ZERO_STRUCT(devmode_ctr);
1291 ZERO_STRUCT(secdesc_ctr);
1293 nt_status = rpccli_spoolss_SetPrinter(pipe_hnd, mem_ctx,
1301 if (!W_ERROR_IS_OK(result) && (W_ERROR_V(result) != W_ERROR_V(WERR_IO_PENDING))) {
1302 printf("cannot set printer-info: %s\n", win_errstr(result));
1306 printf("successfully %s printer %s in Active Directory\n", action_str, sharename);
1309 nt_status = NT_STATUS_OK;
1312 if (is_valid_policy_hnd(&hnd))
1313 rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd, NULL);
1318 NTSTATUS rpc_printer_publish_publish_internals(struct net_context *c,
1319 const DOM_SID *domain_sid,
1320 const char *domain_name,
1321 struct cli_state *cli,
1322 struct rpc_pipe_client *pipe_hnd,
1323 TALLOC_CTX *mem_ctx,
1327 return rpc_printer_publish_internals_args(pipe_hnd, mem_ctx, argc, argv, DSPRINT_PUBLISH);
1330 NTSTATUS rpc_printer_publish_unpublish_internals(struct net_context *c,
1331 const DOM_SID *domain_sid,
1332 const char *domain_name,
1333 struct cli_state *cli,
1334 struct rpc_pipe_client *pipe_hnd,
1335 TALLOC_CTX *mem_ctx,
1339 return rpc_printer_publish_internals_args(pipe_hnd, mem_ctx, argc, argv, DSPRINT_UNPUBLISH);
1342 NTSTATUS rpc_printer_publish_update_internals(struct net_context *c,
1343 const DOM_SID *domain_sid,
1344 const char *domain_name,
1345 struct cli_state *cli,
1346 struct rpc_pipe_client *pipe_hnd,
1347 TALLOC_CTX *mem_ctx,
1351 return rpc_printer_publish_internals_args(pipe_hnd, mem_ctx, argc, argv, DSPRINT_UPDATE);
1355 * List print-queues w.r.t. their publishing state
1357 * All parameters are provided by the run_rpc_command function, except for
1358 * argc, argv which are passed through.
1360 * @param c A net_context structure
1361 * @param domain_sid The domain sid aquired from the remote server
1362 * @param cli A cli_state connected to the server.
1363 * @param mem_ctx Talloc context, destoyed on compleation of the function.
1364 * @param argc Standard main() style argc
1365 * @param argv Standard main() style argv. Initial components are already
1368 * @return Normal NTSTATUS return.
1371 NTSTATUS rpc_printer_publish_list_internals(struct net_context *c,
1372 const DOM_SID *domain_sid,
1373 const char *domain_name,
1374 struct cli_state *cli,
1375 struct rpc_pipe_client *pipe_hnd,
1376 TALLOC_CTX *mem_ctx,
1380 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1381 uint32_t i, num_printers;
1383 const char *printername, *sharename;
1384 union spoolss_PrinterInfo *info_enum;
1385 union spoolss_PrinterInfo info;
1386 struct policy_handle hnd;
1389 if (!get_printer_info(pipe_hnd, mem_ctx, 2, argc, argv, &num_printers, &info_enum))
1392 for (i = 0; i < num_printers; i++) {
1394 /* do some initialization */
1395 printername = info_enum[i].info2.printername;
1396 sharename = info_enum[i].info2.sharename;
1398 if (!printername || !sharename) {
1402 /* open printer handle */
1403 if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, sharename,
1404 PRINTER_ALL_ACCESS, cli->user_name, &hnd))
1407 /* check for existing dst printer */
1408 if (!net_spoolss_getprinter(pipe_hnd, mem_ctx, &hnd, level, &info))
1411 if (!info.info7.guid) {
1414 state = info.info7.action;
1416 case DSPRINT_PUBLISH:
1417 printf("printer [%s] is published", sharename);
1419 printf(", guid: %s", info.info7.guid);
1422 case DSPRINT_UNPUBLISH:
1423 printf("printer [%s] is unpublished\n", sharename);
1425 case DSPRINT_UPDATE:
1426 printf("printer [%s] is currently updating\n", sharename);
1429 printf("unkown state: %d\n", state);
1434 nt_status = NT_STATUS_OK;
1437 if (is_valid_policy_hnd(&hnd))
1438 rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd, NULL);
1444 * Migrate Printer-ACLs from a source server to the destination server
1446 * All parameters are provided by the run_rpc_command function, except for
1447 * argc, argv which are passed through.
1449 * @param c A net_context structure
1450 * @param domain_sid The domain sid aquired from the remote server
1451 * @param cli A cli_state connected to the server.
1452 * @param mem_ctx Talloc context, destoyed on compleation of the function.
1453 * @param argc Standard main() style argc
1454 * @param argv Standard main() style argv. Initial components are already
1457 * @return Normal NTSTATUS return.
1460 NTSTATUS rpc_printer_migrate_security_internals(struct net_context *c,
1461 const DOM_SID *domain_sid,
1462 const char *domain_name,
1463 struct cli_state *cli,
1464 struct rpc_pipe_client *pipe_hnd,
1465 TALLOC_CTX *mem_ctx,
1469 /* TODO: what now, info2 or info3 ?
1470 convince jerry that we should add clientside setacls level 3 at least
1472 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1474 uint32_t num_printers;
1476 const char *printername, *sharename;
1477 struct rpc_pipe_client *pipe_hnd_dst = NULL;
1478 struct policy_handle hnd_src, hnd_dst;
1479 union spoolss_PrinterInfo *info_enum;
1480 struct cli_state *cli_dst = NULL;
1481 union spoolss_PrinterInfo info_src, info_dst;
1483 DEBUG(3,("copying printer ACLs\n"));
1485 /* connect destination PI_SPOOLSS */
1486 nt_status = connect_dst_pipe(c, &cli_dst, &pipe_hnd_dst,
1487 &ndr_table_spoolss.syntax_id);
1488 if (!NT_STATUS_IS_OK(nt_status))
1492 /* enum source printers */
1493 if (!get_printer_info(pipe_hnd, mem_ctx, level, argc, argv, &num_printers, &info_enum)) {
1494 nt_status = NT_STATUS_UNSUCCESSFUL;
1498 if (!num_printers) {
1499 printf ("no printers found on server.\n");
1500 nt_status = NT_STATUS_OK;
1504 /* do something for all printers */
1505 for (i = 0; i < num_printers; i++) {
1507 /* do some initialization */
1508 printername = info_enum[i].info2.printername;
1509 sharename = info_enum[i].info2.sharename;
1511 if (!printername || !sharename) {
1512 nt_status = NT_STATUS_UNSUCCESSFUL;
1516 /* we can reset NT_STATUS here because we do not
1517 get any real NT_STATUS-codes anymore from now on */
1518 nt_status = NT_STATUS_UNSUCCESSFUL;
1520 d_printf("migrating printer ACLs for: [%s] / [%s]\n",
1521 printername, sharename);
1523 /* according to msdn you have specify these access-rights
1524 to see the security descriptor
1525 - READ_CONTROL (DACL)
1526 - ACCESS_SYSTEM_SECURITY (SACL)
1529 /* open src printer handle */
1530 if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, sharename,
1531 MAXIMUM_ALLOWED_ACCESS, cli->user_name, &hnd_src))
1534 /* open dst printer handle */
1535 if (!net_spoolss_open_printer_ex(pipe_hnd_dst, mem_ctx, sharename,
1536 PRINTER_ALL_ACCESS, cli_dst->user_name, &hnd_dst))
1539 /* check for existing dst printer */
1540 if (!net_spoolss_getprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, level, &info_dst))
1543 /* check for existing src printer */
1544 if (!net_spoolss_getprinter(pipe_hnd, mem_ctx, &hnd_src, 3, &info_src))
1547 /* Copy Security Descriptor */
1549 /* copy secdesc (info level 2) */
1550 info_dst.info2.devmode = NULL;
1551 info_dst.info2.secdesc = dup_sec_desc(mem_ctx, info_src.info3.secdesc);
1554 display_sec_desc(info_dst.info2.secdesc);
1556 if (!net_spoolss_setprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, 2, &info_dst))
1559 DEBUGADD(1,("\tSetPrinter of SECDESC succeeded\n"));
1562 /* close printer handles here */
1563 if (is_valid_policy_hnd(&hnd_src)) {
1564 rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd_src, NULL);
1567 if (is_valid_policy_hnd(&hnd_dst)) {
1568 rpccli_spoolss_ClosePrinter(pipe_hnd_dst, mem_ctx, &hnd_dst, NULL);
1573 nt_status = NT_STATUS_OK;
1577 if (is_valid_policy_hnd(&hnd_src)) {
1578 rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd_src, NULL);
1581 if (is_valid_policy_hnd(&hnd_dst)) {
1582 rpccli_spoolss_ClosePrinter(pipe_hnd_dst, mem_ctx, &hnd_dst, NULL);
1586 cli_shutdown(cli_dst);
1592 * Migrate printer-forms from a src server to the dst server
1594 * All parameters are provided by the run_rpc_command function, except for
1595 * argc, argv which are passed through.
1597 * @param c A net_context structure
1598 * @param domain_sid The domain sid aquired from the remote server
1599 * @param cli A cli_state connected to the server.
1600 * @param mem_ctx Talloc context, destoyed on compleation of the function.
1601 * @param argc Standard main() style argc
1602 * @param argv Standard main() style argv. Initial components are already
1605 * @return Normal NTSTATUS return.
1608 NTSTATUS rpc_printer_migrate_forms_internals(struct net_context *c,
1609 const DOM_SID *domain_sid,
1610 const char *domain_name,
1611 struct cli_state *cli,
1612 struct rpc_pipe_client *pipe_hnd,
1613 TALLOC_CTX *mem_ctx,
1617 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1620 uint32_t num_printers;
1622 const char *printername, *sharename;
1623 struct rpc_pipe_client *pipe_hnd_dst = NULL;
1624 struct policy_handle hnd_src, hnd_dst;
1625 union spoolss_PrinterInfo *info_enum;
1626 union spoolss_PrinterInfo info_dst;
1628 union spoolss_FormInfo *forms;
1629 struct cli_state *cli_dst = NULL;
1631 DEBUG(3,("copying forms\n"));
1633 /* connect destination PI_SPOOLSS */
1634 nt_status = connect_dst_pipe(c, &cli_dst, &pipe_hnd_dst,
1635 &ndr_table_spoolss.syntax_id);
1636 if (!NT_STATUS_IS_OK(nt_status))
1639 /* enum src printers */
1640 if (!get_printer_info(pipe_hnd, mem_ctx, 2, argc, argv, &num_printers, &info_enum)) {
1641 nt_status = NT_STATUS_UNSUCCESSFUL;
1645 if (!num_printers) {
1646 printf ("no printers found on server.\n");
1647 nt_status = NT_STATUS_OK;
1651 /* do something for all printers */
1652 for (i = 0; i < num_printers; i++) {
1654 /* do some initialization */
1655 printername = info_enum[i].info2.printername;
1656 sharename = info_enum[i].info2.sharename;
1658 if (!printername || !sharename) {
1659 nt_status = NT_STATUS_UNSUCCESSFUL;
1662 /* we can reset NT_STATUS here because we do not
1663 get any real NT_STATUS-codes anymore from now on */
1664 nt_status = NT_STATUS_UNSUCCESSFUL;
1666 d_printf("migrating printer forms for: [%s] / [%s]\n",
1667 printername, sharename);
1670 /* open src printer handle */
1671 if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, sharename,
1672 MAXIMUM_ALLOWED_ACCESS, cli->user_name, &hnd_src))
1675 /* open dst printer handle */
1676 if (!net_spoolss_open_printer_ex(pipe_hnd_dst, mem_ctx, sharename,
1677 PRINTER_ALL_ACCESS, cli->user_name, &hnd_dst))
1680 /* check for existing dst printer */
1681 if (!net_spoolss_getprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, level, &info_dst))
1684 /* finally migrate forms */
1685 if (!net_spoolss_enumforms(pipe_hnd, mem_ctx, &hnd_src, level, &num_forms, &forms))
1688 DEBUG(1,("got %d forms for printer\n", num_forms));
1691 for (f = 0; f < num_forms; f++) {
1693 union spoolss_AddFormInfo info;
1696 /* only migrate FORM_PRINTER types, according to jerry
1697 FORM_BUILTIN-types are hard-coded in samba */
1698 if (forms[f].info1.flags != SPOOLSS_FORM_PRINTER)
1702 d_printf("\tmigrating form # %d [%s] of type [%d]\n",
1703 f, forms[f].info1.form_name,
1704 forms[f].info1.flags);
1706 info.info1 = (struct spoolss_AddFormInfo1 *)
1707 (void *)&forms[f].info1;
1709 /* FIXME: there might be something wrong with samba's
1711 status = rpccli_spoolss_AddForm(pipe_hnd_dst, mem_ctx,
1716 if (!W_ERROR_IS_OK(result)) {
1717 d_printf("\tAddForm form %d: [%s] refused.\n",
1718 f, forms[f].info1.form_name);
1722 DEBUGADD(1,("\tAddForm of [%s] succeeded\n",
1723 forms[f].info1.form_name));
1727 /* close printer handles here */
1728 if (is_valid_policy_hnd(&hnd_src)) {
1729 rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd_src, NULL);
1732 if (is_valid_policy_hnd(&hnd_dst)) {
1733 rpccli_spoolss_ClosePrinter(pipe_hnd_dst, mem_ctx, &hnd_dst, NULL);
1737 nt_status = NT_STATUS_OK;
1741 if (is_valid_policy_hnd(&hnd_src))
1742 rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd_src, NULL);
1744 if (is_valid_policy_hnd(&hnd_dst))
1745 rpccli_spoolss_ClosePrinter(pipe_hnd_dst, mem_ctx, &hnd_dst, NULL);
1748 cli_shutdown(cli_dst);
1754 * Migrate printer-drivers from a src server to the dst server
1756 * All parameters are provided by the run_rpc_command function, except for
1757 * argc, argv which are passed through.
1759 * @param c A net_context structure
1760 * @param domain_sid The domain sid aquired from the remote server
1761 * @param cli A cli_state connected to the server.
1762 * @param mem_ctx Talloc context, destoyed on compleation of the function.
1763 * @param argc Standard main() style argc
1764 * @param argv Standard main() style argv. Initial components are already
1767 * @return Normal NTSTATUS return.
1770 NTSTATUS rpc_printer_migrate_drivers_internals(struct net_context *c,
1771 const DOM_SID *domain_sid,
1772 const char *domain_name,
1773 struct cli_state *cli,
1774 struct rpc_pipe_client *pipe_hnd,
1775 TALLOC_CTX *mem_ctx,
1779 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1781 uint32_t num_printers;
1783 const char *printername, *sharename;
1784 bool got_src_driver_share = false;
1785 bool got_dst_driver_share = false;
1786 struct rpc_pipe_client *pipe_hnd_dst = NULL;
1787 struct policy_handle hnd_src, hnd_dst;
1788 union spoolss_DriverInfo drv_info_src;
1789 union spoolss_PrinterInfo *info_enum;
1790 union spoolss_PrinterInfo info_dst;
1791 struct cli_state *cli_dst = NULL;
1792 struct cli_state *cli_share_src = NULL;
1793 struct cli_state *cli_share_dst = NULL;
1794 const char *drivername = NULL;
1796 DEBUG(3,("copying printer-drivers\n"));
1798 nt_status = connect_dst_pipe(c, &cli_dst, &pipe_hnd_dst,
1799 &ndr_table_spoolss.syntax_id);
1800 if (!NT_STATUS_IS_OK(nt_status))
1803 /* open print$-share on the src server */
1804 nt_status = connect_to_service(c, &cli_share_src, &cli->dest_ss,
1805 cli->desthost, "print$", "A:");
1806 if (!NT_STATUS_IS_OK(nt_status))
1809 got_src_driver_share = true;
1812 /* open print$-share on the dst server */
1813 nt_status = connect_to_service(c, &cli_share_dst, &cli_dst->dest_ss,
1814 cli_dst->desthost, "print$", "A:");
1815 if (!NT_STATUS_IS_OK(nt_status))
1818 got_dst_driver_share = true;
1821 /* enum src printers */
1822 if (!get_printer_info(pipe_hnd, mem_ctx, 2, argc, argv, &num_printers, &info_enum)) {
1823 nt_status = NT_STATUS_UNSUCCESSFUL;
1827 if (num_printers == 0) {
1828 printf ("no printers found on server.\n");
1829 nt_status = NT_STATUS_OK;
1834 /* do something for all printers */
1835 for (p = 0; p < num_printers; p++) {
1837 /* do some initialization */
1838 printername = info_enum[p].info2.printername;
1839 sharename = info_enum[p].info2.sharename;
1841 if (!printername || !sharename) {
1842 nt_status = NT_STATUS_UNSUCCESSFUL;
1846 /* we can reset NT_STATUS here because we do not
1847 get any real NT_STATUS-codes anymore from now on */
1848 nt_status = NT_STATUS_UNSUCCESSFUL;
1850 d_printf("migrating printer driver for: [%s] / [%s]\n",
1851 printername, sharename);
1853 /* open dst printer handle */
1854 if (!net_spoolss_open_printer_ex(pipe_hnd_dst, mem_ctx, sharename,
1855 PRINTER_ALL_ACCESS, cli->user_name, &hnd_dst))
1858 /* check for existing dst printer */
1859 if (!net_spoolss_getprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, 2, &info_dst))
1863 /* open src printer handle */
1864 if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, sharename,
1865 MAXIMUM_ALLOWED_ACCESS,
1866 pipe_hnd->auth->user_name,
1870 /* in a first step call getdriver for each shared printer (per arch)
1871 to get a list of all files that have to be copied */
1873 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1876 if (!net_spoolss_getprinterdriver(pipe_hnd, mem_ctx, &hnd_src,
1877 level, archi_table[i].long_archi,
1878 archi_table[i].version, &drv_info_src))
1881 drivername = drv_info_src.info3.driver_name;
1884 display_print_driver3(&drv_info_src.info3);
1886 /* check arch dir */
1887 nt_status = check_arch_dir(cli_share_dst, archi_table[i].short_archi);
1888 if (!NT_STATUS_IS_OK(nt_status))
1892 /* copy driver-files */
1893 nt_status = copy_print_driver_3(c, mem_ctx, cli_share_src, cli_share_dst,
1894 archi_table[i].short_archi,
1895 &drv_info_src.info3);
1896 if (!NT_STATUS_IS_OK(nt_status))
1901 if (!net_spoolss_addprinterdriver(pipe_hnd_dst, mem_ctx, level, &drv_info_src)) {
1902 nt_status = NT_STATUS_UNSUCCESSFUL;
1906 DEBUGADD(1,("Sucessfully added driver [%s] for printer [%s]\n",
1907 drivername, printername));
1911 if (!drivername || strlen(drivername) == 0) {
1912 DEBUGADD(1,("Did not get driver for printer %s\n",
1918 info_dst.info2.drivername = drivername;
1920 if (!net_spoolss_setprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, 2, &info_dst)) {
1921 nt_status = NT_STATUS_UNSUCCESSFUL;
1925 DEBUGADD(1,("Sucessfully set driver %s for printer %s\n",
1926 drivername, printername));
1929 if (is_valid_policy_hnd(&hnd_dst)) {
1930 rpccli_spoolss_ClosePrinter(pipe_hnd_dst, mem_ctx, &hnd_dst, NULL);
1934 if (is_valid_policy_hnd(&hnd_src)) {
1935 rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd_src, NULL);
1939 nt_status = NT_STATUS_OK;
1943 if (is_valid_policy_hnd(&hnd_src))
1944 rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd_src, NULL);
1946 if (is_valid_policy_hnd(&hnd_dst))
1947 rpccli_spoolss_ClosePrinter(pipe_hnd_dst, mem_ctx, &hnd_dst, NULL);
1950 cli_shutdown(cli_dst);
1953 if (got_src_driver_share)
1954 cli_shutdown(cli_share_src);
1956 if (got_dst_driver_share)
1957 cli_shutdown(cli_share_dst);
1964 * Migrate printer-queues from a src to the dst server
1965 * (requires a working "addprinter command" to be installed for the local smbd)
1967 * All parameters are provided by the run_rpc_command function, except for
1968 * argc, argv which are passed through.
1970 * @param c A net_context structure
1971 * @param domain_sid The domain sid aquired from the remote server
1972 * @param cli A cli_state connected to the server.
1973 * @param mem_ctx Talloc context, destoyed on compleation of the function.
1974 * @param argc Standard main() style argc
1975 * @param argv Standard main() style argv. Initial components are already
1978 * @return Normal NTSTATUS return.
1981 NTSTATUS rpc_printer_migrate_printers_internals(struct net_context *c,
1982 const DOM_SID *domain_sid,
1983 const char *domain_name,
1984 struct cli_state *cli,
1985 struct rpc_pipe_client *pipe_hnd,
1986 TALLOC_CTX *mem_ctx,
1991 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1992 uint32_t i = 0, num_printers;
1994 union spoolss_PrinterInfo info_dst, info_src;
1995 union spoolss_PrinterInfo *info_enum;
1996 struct cli_state *cli_dst = NULL;
1997 struct policy_handle hnd_dst, hnd_src;
1998 const char *printername, *sharename;
1999 struct rpc_pipe_client *pipe_hnd_dst = NULL;
2000 struct spoolss_SetPrinterInfoCtr info_ctr;
2002 DEBUG(3,("copying printers\n"));
2004 /* connect destination PI_SPOOLSS */
2005 nt_status = connect_dst_pipe(c, &cli_dst, &pipe_hnd_dst,
2006 &ndr_table_spoolss.syntax_id);
2007 if (!NT_STATUS_IS_OK(nt_status))
2011 if (!get_printer_info(pipe_hnd, mem_ctx, level, argc, argv, &num_printers, &info_enum)) {
2012 nt_status = NT_STATUS_UNSUCCESSFUL;
2016 if (!num_printers) {
2017 printf ("no printers found on server.\n");
2018 nt_status = NT_STATUS_OK;
2022 /* do something for all printers */
2023 for (i = 0; i < num_printers; i++) {
2025 /* do some initialization */
2026 printername = info_enum[i].info2.printername;
2027 sharename = info_enum[i].info2.sharename;
2029 if (!printername || !sharename) {
2030 nt_status = NT_STATUS_UNSUCCESSFUL;
2033 /* we can reset NT_STATUS here because we do not
2034 get any real NT_STATUS-codes anymore from now on */
2035 nt_status = NT_STATUS_UNSUCCESSFUL;
2037 d_printf("migrating printer queue for: [%s] / [%s]\n",
2038 printername, sharename);
2040 /* open dst printer handle */
2041 if (!net_spoolss_open_printer_ex(pipe_hnd_dst, mem_ctx, sharename,
2042 PRINTER_ALL_ACCESS, cli->user_name, &hnd_dst)) {
2044 DEBUG(1,("could not open printer: %s\n", sharename));
2047 /* check for existing dst printer */
2048 if (!net_spoolss_getprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, level, &info_dst)) {
2049 printf ("could not get printer, creating printer.\n");
2051 DEBUG(1,("printer already exists: %s\n", sharename));
2052 /* close printer handle here - dst only, not got src yet. */
2053 if (is_valid_policy_hnd(&hnd_dst)) {
2054 rpccli_spoolss_ClosePrinter(pipe_hnd_dst, mem_ctx, &hnd_dst, NULL);
2059 /* now get again src printer ctr via getprinter,
2060 we first need a handle for that */
2062 /* open src printer handle */
2063 if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, sharename,
2064 MAXIMUM_ALLOWED_ACCESS, cli->user_name, &hnd_src))
2067 /* getprinter on the src server */
2068 if (!net_spoolss_getprinter(pipe_hnd, mem_ctx, &hnd_src, level, &info_src))
2071 /* copy each src printer to a dst printer 1:1,
2072 maybe some values have to be changed though */
2073 d_printf("creating printer: %s\n", printername);
2075 info_ctr.level = level;
2076 info_ctr.info.info2 = (struct spoolss_SetPrinterInfo2 *)
2077 (void *)&info_src.info2;
2079 result = rpccli_spoolss_addprinterex(pipe_hnd_dst,
2083 if (W_ERROR_IS_OK(result))
2084 d_printf ("printer [%s] successfully added.\n", printername);
2085 else if (W_ERROR_V(result) == W_ERROR_V(WERR_PRINTER_ALREADY_EXISTS))
2086 d_fprintf (stderr, "printer [%s] already exists.\n", printername);
2088 d_fprintf (stderr, "could not create printer [%s]\n", printername);
2092 /* close printer handles here */
2093 if (is_valid_policy_hnd(&hnd_src)) {
2094 rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd_src, NULL);
2097 if (is_valid_policy_hnd(&hnd_dst)) {
2098 rpccli_spoolss_ClosePrinter(pipe_hnd_dst, mem_ctx, &hnd_dst, NULL);
2102 nt_status = NT_STATUS_OK;
2105 if (is_valid_policy_hnd(&hnd_src))
2106 rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd_src, NULL);
2108 if (is_valid_policy_hnd(&hnd_dst))
2109 rpccli_spoolss_ClosePrinter(pipe_hnd_dst, mem_ctx, &hnd_dst, NULL);
2112 cli_shutdown(cli_dst);
2118 * Migrate Printer-Settings from a src server to the dst server
2119 * (for this to work, printers and drivers already have to be migrated earlier)
2121 * All parameters are provided by the run_rpc_command function, except for
2122 * argc, argv which are passed through.
2124 * @param c A net_context structure
2125 * @param domain_sid The domain sid aquired from the remote server
2126 * @param cli A cli_state connected to the server.
2127 * @param mem_ctx Talloc context, destoyed on compleation of the function.
2128 * @param argc Standard main() style argc
2129 * @param argv Standard main() style argv. Initial components are already
2132 * @return Normal NTSTATUS return.
2135 NTSTATUS rpc_printer_migrate_settings_internals(struct net_context *c,
2136 const DOM_SID *domain_sid,
2137 const char *domain_name,
2138 struct cli_state *cli,
2139 struct rpc_pipe_client *pipe_hnd,
2140 TALLOC_CTX *mem_ctx,
2145 /* FIXME: Here the nightmare begins */
2148 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
2149 uint32_t i = 0, p = 0, j = 0;
2150 uint32_t num_printers;
2152 const char *printername, *sharename;
2153 struct rpc_pipe_client *pipe_hnd_dst = NULL;
2154 struct policy_handle hnd_src, hnd_dst;
2155 union spoolss_PrinterInfo *info_enum;
2156 union spoolss_PrinterInfo info_dst_publish;
2157 union spoolss_PrinterInfo info_dst;
2158 struct cli_state *cli_dst = NULL;
2159 char *devicename = NULL, *unc_name = NULL, *url = NULL;
2160 const char *longname;
2161 const char **keylist = NULL;
2164 ZERO_STRUCT(info_dst_publish);
2166 DEBUG(3,("copying printer settings\n"));
2168 /* connect destination PI_SPOOLSS */
2169 nt_status = connect_dst_pipe(c, &cli_dst, &pipe_hnd_dst,
2170 &ndr_table_spoolss.syntax_id);
2171 if (!NT_STATUS_IS_OK(nt_status))
2174 /* enum src printers */
2175 if (!get_printer_info(pipe_hnd, mem_ctx, level, argc, argv, &num_printers, &info_enum)) {
2176 nt_status = NT_STATUS_UNSUCCESSFUL;
2180 if (!num_printers) {
2181 printf ("no printers found on server.\n");
2182 nt_status = NT_STATUS_OK;
2187 /* needed for dns-strings in regkeys */
2188 longname = get_mydnsfullname();
2190 nt_status = NT_STATUS_UNSUCCESSFUL;
2194 /* do something for all printers */
2195 for (i = 0; i < num_printers; i++) {
2197 uint32_t value_offered = 0, value_needed;
2198 uint32_t data_offered = 0, data_needed;
2199 enum winreg_Type type;
2200 uint8_t *buffer = NULL;
2201 const char *value_name = NULL;
2203 /* do some initialization */
2204 printername = info_enum[i].info2.printername;
2205 sharename = info_enum[i].info2.sharename;
2207 if (!printername || !sharename) {
2208 nt_status = NT_STATUS_UNSUCCESSFUL;
2211 /* we can reset NT_STATUS here because we do not
2212 get any real NT_STATUS-codes anymore from now on */
2213 nt_status = NT_STATUS_UNSUCCESSFUL;
2215 d_printf("migrating printer settings for: [%s] / [%s]\n",
2216 printername, sharename);
2219 /* open src printer handle */
2220 if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, sharename,
2221 MAXIMUM_ALLOWED_ACCESS, cli->user_name, &hnd_src))
2224 /* open dst printer handle */
2225 if (!net_spoolss_open_printer_ex(pipe_hnd_dst, mem_ctx, sharename,
2226 PRINTER_ALL_ACCESS, cli_dst->user_name, &hnd_dst))
2229 /* check for existing dst printer */
2230 if (!net_spoolss_getprinter(pipe_hnd_dst, mem_ctx, &hnd_dst,
2235 /* STEP 1: COPY DEVICE-MODE and other
2236 PRINTER_INFO_2-attributes
2239 info_dst.info2 = info_enum[i].info2;
2241 /* why is the port always disconnected when the printer
2242 is correctly installed (incl. driver ???) */
2243 info_dst.info2.portname = SAMBA_PRINTER_PORT_NAME;
2245 /* check if printer is published */
2246 if (info_enum[i].info2.attributes & PRINTER_ATTRIBUTE_PUBLISHED) {
2248 /* check for existing dst printer */
2249 if (!net_spoolss_getprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, 7, &info_dst_publish))
2252 info_dst_publish.info7.action = DSPRINT_PUBLISH;
2254 /* ignore false from setprinter due to WERR_IO_PENDING */
2255 net_spoolss_setprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, 7, &info_dst_publish);
2257 DEBUG(3,("republished printer\n"));
2260 if (info_enum[i].info2.devmode != NULL) {
2262 /* copy devmode (info level 2) */
2263 info_dst.info2.devmode = info_enum[i].info2.devmode;
2265 /* do not copy security descriptor (we have another
2266 * command for that) */
2267 info_dst.info2.secdesc = NULL;
2270 info_dst.info2.devmode.devicename =
2271 talloc_asprintf(mem_ctx, "\\\\%s\\%s",
2272 longname, printername);
2273 if (!info_dst.info2.devmode.devicename) {
2274 nt_status = NT_STATUS_NO_MEMORY;
2278 if (!net_spoolss_setprinter(pipe_hnd_dst, mem_ctx, &hnd_dst,
2282 DEBUGADD(1,("\tSetPrinter of DEVICEMODE succeeded\n"));
2285 /* STEP 2: COPY REGISTRY VALUES */
2287 /* please keep in mind that samba parse_spools gives horribly
2288 crippled results when used to rpccli_spoolss_enumprinterdataex
2289 a win2k3-server. (Bugzilla #1851)
2290 FIXME: IIRC I've seen it too on a win2k-server
2293 /* enumerate data on src handle */
2294 nt_status = rpccli_spoolss_EnumPrinterData(pipe_hnd, mem_ctx,
2306 data_offered = data_needed;
2307 value_offered = value_needed;
2308 buffer = talloc_zero_array(mem_ctx, uint8_t, data_needed);
2309 value_name = talloc_zero_array(mem_ctx, char, value_needed);
2311 /* loop for all printerdata of "PrinterDriverData" */
2312 while (NT_STATUS_IS_OK(nt_status) && W_ERROR_IS_OK(result)) {
2314 nt_status = rpccli_spoolss_EnumPrinterData(pipe_hnd, mem_ctx,
2325 /* loop for all reg_keys */
2326 if (NT_STATUS_IS_OK(nt_status) && W_ERROR_IS_OK(result)) {
2328 struct regval_blob v;
2330 union spoolss_PrinterData printer_data;
2333 if (c->opt_verbose) {
2334 fstrcpy(v.valuename, value_name);
2336 v.size = data_offered;
2338 display_reg_value(SPOOL_PRINTERDATA_KEY, v);
2341 result = pull_spoolss_PrinterData(mem_ctx,
2345 if (!W_ERROR_IS_OK(result)) {
2350 if (!net_spoolss_setprinterdata(pipe_hnd_dst, mem_ctx,
2351 &hnd_dst, value_name,
2352 type, printer_data))
2355 DEBUGADD(1,("\tSetPrinterData of [%s] succeeded\n",
2360 /* STEP 3: COPY SUBKEY VALUES */
2362 /* here we need to enum all printer_keys and then work
2363 on the result with enum_printer_key_ex. nt4 does not
2364 respond to enumprinterkey, win2k does, so continue
2365 in case of an error */
2367 if (!net_spoolss_enumprinterkey(pipe_hnd, mem_ctx, &hnd_src, "", &keylist)) {
2368 printf("got no key-data\n");
2373 /* work on a list of printer keys
2374 each key has to be enumerated to get all required
2375 information. information is then set via setprinterdataex-calls */
2377 if (keylist == NULL)
2380 for (i=0; keylist && keylist[i] != NULL; i++) {
2382 const char *subkey = keylist[i];
2384 struct spoolss_PrinterEnumValues *info;
2386 /* enumerate all src subkeys */
2387 if (!net_spoolss_enumprinterdataex(pipe_hnd, mem_ctx, 0,
2393 for (j=0; j < count; j++) {
2395 struct regval_blob value;
2398 /* although samba replies with sane data in most cases we
2399 should try to avoid writing wrong registry data */
2401 if (strequal(info[j].value_name, SPOOL_REG_PORTNAME) ||
2402 strequal(info[j].value_name, SPOOL_REG_UNCNAME) ||
2403 strequal(info[j].value_name, SPOOL_REG_URL) ||
2404 strequal(info[j].value_name, SPOOL_REG_SHORTSERVERNAME) ||
2405 strequal(info[j].value_name, SPOOL_REG_SERVERNAME)) {
2407 if (strequal(info[j].value_name, SPOOL_REG_PORTNAME)) {
2409 /* although windows uses a multi-sz, we use a sz */
2410 init_unistr2(&data, SAMBA_PRINTER_PORT_NAME, UNI_STR_TERMINATE);
2411 fstrcpy(value.valuename, SPOOL_REG_PORTNAME);
2414 if (strequal(info[j].value_name, SPOOL_REG_UNCNAME)) {
2416 if (asprintf(&unc_name, "\\\\%s\\%s", longname, sharename) < 0) {
2417 nt_status = NT_STATUS_NO_MEMORY;
2420 init_unistr2(&data, unc_name, UNI_STR_TERMINATE);
2421 fstrcpy(value.valuename, SPOOL_REG_UNCNAME);
2424 if (strequal(info[j].value_name, SPOOL_REG_URL)) {
2429 /* FIXME: should we really do that ??? */
2430 if (asprintf(&url, "http://%s:631/printers/%s", longname, sharename) < 0) {
2431 nt_status = NT_STATUS_NO_MEMORY;
2434 init_unistr2(&data, url, UNI_STR_TERMINATE);
2435 fstrcpy(value.valuename, SPOOL_REG_URL);
2439 if (strequal(info[j].value_name, SPOOL_REG_SERVERNAME)) {
2441 init_unistr2(&data, longname, UNI_STR_TERMINATE);
2442 fstrcpy(value.valuename, SPOOL_REG_SERVERNAME);
2445 if (strequal(info[j].value_name, SPOOL_REG_SHORTSERVERNAME)) {
2447 init_unistr2(&data, global_myname(), UNI_STR_TERMINATE);
2448 fstrcpy(value.valuename, SPOOL_REG_SHORTSERVERNAME);
2451 value.type = REG_SZ;
2452 value.size = data.uni_str_len * 2;
2454 value.data_p = (uint8_t *)TALLOC_MEMDUP(mem_ctx, data.buffer, value.size);
2456 value.data_p = NULL;
2460 display_reg_value(subkey, value);
2462 /* here we have to set all subkeys on the dst server */
2463 if (!net_spoolss_setprinterdataex(pipe_hnd_dst, mem_ctx, &hnd_dst,
2469 struct regval_blob v;
2472 result = push_spoolss_PrinterData(mem_ctx, &blob,
2475 if (!W_ERROR_IS_OK(result)) {
2479 fstrcpy(v.valuename, info[j].value_name);
2480 v.type = info[j].type;
2481 v.data_p = blob.data;
2482 v.size = blob.length;
2484 if (c->opt_verbose) {
2485 display_reg_value(subkey, v);
2488 /* here we have to set all subkeys on the dst server */
2489 if (!net_spoolss_setprinterdataex(pipe_hnd_dst, mem_ctx, &hnd_dst,
2496 DEBUGADD(1,("\tSetPrinterDataEx of key [%s\\%s] succeeded\n",
2497 subkey, info[j].value_name));
2502 TALLOC_FREE(keylist);
2504 /* close printer handles here */
2505 if (is_valid_policy_hnd(&hnd_src)) {
2506 rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd_src, NULL);
2509 if (is_valid_policy_hnd(&hnd_dst)) {
2510 rpccli_spoolss_ClosePrinter(pipe_hnd_dst, mem_ctx, &hnd_dst, NULL);
2515 nt_status = NT_STATUS_OK;
2518 SAFE_FREE(devicename);
2520 SAFE_FREE(unc_name);
2522 if (is_valid_policy_hnd(&hnd_src))
2523 rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd_src, NULL);
2525 if (is_valid_policy_hnd(&hnd_dst))
2526 rpccli_spoolss_ClosePrinter(pipe_hnd_dst, mem_ctx, &hnd_dst, NULL);
2529 cli_shutdown(cli_dst);