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, REGISTRY_VALUE 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;
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 fnum_src = cli_nt_create(cli_share_src, src_name, READ_CONTROL_ACCESS);
167 if (fnum_src == -1) {
168 DEBUGADD(0,("cannot open %s %s on originating server %s\n",
169 is_file?"file":"dir", src_name, cli_errstr(cli_share_src)));
170 nt_status = cli_nt_error(cli_share_src);
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 (!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 fnum_dst = cli_nt_create(cli_share_dst, dst_name, WRITE_DAC_ACCESS | WRITE_OWNER_ACCESS);
207 if (fnum_dst == -1) {
208 DEBUG(0,("failed to open %s on the destination server: %s: %s\n",
209 is_file?"file":"dir", dst_name, cli_errstr(cli_share_dst)));
210 nt_status = cli_nt_error(cli_share_dst);
214 if (copy_timestamps) {
217 if (!cli_setattrE(cli_share_dst, fnum_dst, f_ctime, f_atime, f_mtime)) {
218 DEBUG(0,("failed to set file-attrs (timestamps): %s\n",
219 cli_errstr(cli_share_dst)));
220 nt_status = cli_nt_error(cli_share_dst);
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 (!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 (!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 (!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;
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 fnum_src = cli_open(cli_share_src, src_name, O_RDONLY, DENY_NONE);
325 fnum_src = cli_nt_create(cli_share_src, src_name, READ_CONTROL_ACCESS);
327 if (fnum_src == -1) {
328 DEBUGADD(0,("cannot open %s %s on originating server %s\n",
329 is_file ? "file":"dir",
330 src_name, cli_errstr(cli_share_src)));
331 nt_status = cli_nt_error(cli_share_src);
338 /* open file on the destination server */
339 DEBUGADD(3,("opening file %s on destination server\n", dst_name));
340 fnum_dst = cli_open(cli_share_dst, dst_name,
341 O_RDWR|O_CREAT|O_TRUNC, DENY_NONE);
343 if (fnum_dst == -1) {
344 DEBUGADD(1,("cannot create file %s on destination server: %s\n",
345 dst_name, cli_errstr(cli_share_dst)));
346 nt_status = cli_nt_error(cli_share_dst);
350 /* allocate memory */
351 if (!(data = (char *)SMB_MALLOC(read_size))) {
352 d_fprintf(stderr, "malloc fail for size %d\n", read_size);
353 nt_status = NT_STATUS_NO_MEMORY;
360 if (c->opt_verbose) {
362 d_printf("copying [\\\\%s\\%s%s] => [\\\\%s\\%s%s] "
363 "%s ACLs and %s DOS Attributes %s\n",
364 cli_share_src->desthost, cli_share_src->share, src_name,
365 cli_share_dst->desthost, cli_share_dst->share, dst_name,
366 copy_acls ? "with" : "without",
367 copy_attrs ? "with" : "without",
368 copy_timestamps ? "(preserving timestamps)" : "" );
376 n = cli_read(cli_share_src, fnum_src, data, nread,
382 ret = cli_write(cli_share_dst, fnum_dst, 0, data,
386 d_fprintf(stderr, "Error writing file: %s\n",
387 cli_errstr(cli_share_dst));
388 nt_status = cli_nt_error(cli_share_dst);
396 if (!is_file && !cli_chkpath(cli_share_dst, dst_name)) {
399 DEBUGADD(3,("creating dir %s on the destination server\n",
402 if (!cli_mkdir(cli_share_dst, dst_name)) {
403 DEBUG(0,("cannot create directory %s: %s\n",
404 dst_name, cli_errstr(cli_share_dst)));
405 nt_status = NT_STATUS_NO_SUCH_FILE;
408 if (!cli_chkpath(cli_share_dst, dst_name)) {
409 d_fprintf(stderr, "cannot check for directory %s: %s\n",
410 dst_name, cli_errstr(cli_share_dst));
417 if (!cli_close(cli_share_src, fnum_src)) {
418 d_fprintf(stderr, "could not close file on originating server: %s\n",
419 cli_errstr(cli_share_src));
420 nt_status = cli_nt_error(cli_share_src);
424 if (is_file && !cli_close(cli_share_dst, fnum_dst)) {
425 d_fprintf(stderr, "could not close file on destination server: %s\n",
426 cli_errstr(cli_share_dst));
427 nt_status = cli_nt_error(cli_share_dst);
431 /* possibly we have to copy some file-attributes / acls / sd */
432 nt_status = net_copy_fileattr(c, mem_ctx, cli_share_src, cli_share_dst,
433 src_name, dst_name, copy_acls,
434 copy_attrs, copy_timestamps, is_file);
435 if (!NT_STATUS_IS_OK(nt_status))
439 nt_status = NT_STATUS_OK;
445 cli_close(cli_share_src, fnum_src);
448 cli_close(cli_share_dst, fnum_dst);
456 * Copy a driverfile from on connected share to another connected share
457 * This silently assumes that a driver-file is picked up from
459 * \\src_server\print$\{arch}\{version}\file
463 * \\dst_server\print$\{arch}\file
465 * to be added via setdriver-calls later.
466 * @param c A net_context structure
467 * @param mem_ctx A talloc-context
468 * @param cli_share_src A cli_state connected to source print$-share
469 * @param cli_share_dst A cli_state connected to destination print$-share
470 * @param file The file-name to be copied
471 * @param short_archi The name of the driver-architecture (short form)
473 * @return Normal NTSTATUS return.
476 static NTSTATUS net_copy_driverfile(struct net_context *c,
478 struct cli_state *cli_share_src,
479 struct cli_state *cli_share_dst,
480 const char *file, const char *short_archi) {
482 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
494 /* scroll through the file until we have the part
495 beyond archi_table.short_archi */
497 while (next_token_talloc(mem_ctx, &p, &tok, "\\")) {
498 if (strequal(tok, short_archi)) {
499 next_token_talloc(mem_ctx, &p, &version, "\\");
500 next_token_talloc(mem_ctx, &p, &filename, "\\");
504 /* build source file name */
505 if (asprintf(&src_name, "\\%s\\%s\\%s", short_archi, version, filename) < 0 )
506 return NT_STATUS_NO_MEMORY;
509 /* create destination file name */
510 if (asprintf(&dst_name, "\\%s\\%s", short_archi, filename) < 0 )
511 return NT_STATUS_NO_MEMORY;
514 /* finally copy the file */
515 nt_status = net_copy_file(c, mem_ctx, cli_share_src, cli_share_dst,
516 src_name, dst_name, false, false, false, true);
517 if (!NT_STATUS_IS_OK(nt_status))
520 nt_status = NT_STATUS_OK;
530 * Check for existing Architecture directory on a given server
532 * @param cli_share A cli_state connected to a print$-share
533 * @param short_archi The Architecture for the print-driver
535 * @return Normal NTSTATUS return.
538 static NTSTATUS check_arch_dir(struct cli_state *cli_share, const char *short_archi)
541 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
544 if (asprintf(&dir, "\\%s", short_archi) < 0) {
545 return NT_STATUS_NO_MEMORY;
548 DEBUG(10,("creating print-driver dir for architecture: %s\n",
551 if (!cli_mkdir(cli_share, dir)) {
552 DEBUG(1,("cannot create directory %s: %s\n",
553 dir, cli_errstr(cli_share)));
554 nt_status = NT_STATUS_NO_SUCH_FILE;
557 if (!cli_chkpath(cli_share, dir)) {
558 d_fprintf(stderr, "cannot check %s: %s\n",
559 dir, cli_errstr(cli_share));
563 nt_status = NT_STATUS_OK;
571 * Copy a print-driver (level 3) from one connected print$-share to another
572 * connected print$-share
574 * @param c A net_context structure
575 * @param mem_ctx A talloc-context
576 * @param cli_share_src A cli_state connected to a print$-share
577 * @param cli_share_dst A cli_state connected to a print$-share
578 * @param short_archi The Architecture for the print-driver
579 * @param i1 The DRIVER_INFO_3-struct
581 * @return Normal NTSTATUS return.
584 static NTSTATUS copy_print_driver_3(struct net_context *c,
586 struct cli_state *cli_share_src,
587 struct cli_state *cli_share_dst,
588 const char *short_archi,
589 struct spoolss_DriverInfo3 *r)
591 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
599 d_printf("copying driver: [%s], for architecture: [%s], version: [%d]\n",
600 r->driver_name, short_archi, r->version);
602 nt_status = net_copy_driverfile(c, mem_ctx, cli_share_src, cli_share_dst,
603 r->driver_path, short_archi);
604 if (!NT_STATUS_IS_OK(nt_status))
607 nt_status = net_copy_driverfile(c, mem_ctx, cli_share_src, cli_share_dst,
608 r->data_file, short_archi);
609 if (!NT_STATUS_IS_OK(nt_status))
612 nt_status = net_copy_driverfile(c, mem_ctx, cli_share_src, cli_share_dst,
613 r->config_file, short_archi);
614 if (!NT_STATUS_IS_OK(nt_status))
617 nt_status = net_copy_driverfile(c, mem_ctx, cli_share_src, cli_share_dst,
618 r->help_file, short_archi);
619 if (!NT_STATUS_IS_OK(nt_status))
622 for (i=0; r->dependent_files[i] != NULL; i++) {
624 nt_status = net_copy_driverfile(c, mem_ctx,
625 cli_share_src, cli_share_dst,
626 r->dependent_files[i], short_archi);
627 if (!NT_STATUS_IS_OK(nt_status)) {
636 * net_spoolss-functions
637 * =====================
639 * the net_spoolss-functions aim to simplify spoolss-client-functions
640 * required during the migration-process wrt buffer-sizes, returned
643 * this greatly reduces the complexitiy of the migrate-functions.
647 static bool net_spoolss_enum_printers(struct rpc_pipe_client *pipe_hnd,
652 uint32_t *num_printers,
653 union spoolss_PrinterInfo **info)
659 result = rpccli_spoolss_enumprinters(pipe_hnd, mem_ctx,
666 if (!W_ERROR_IS_OK(result)) {
667 printf("cannot enum printers: %s\n", win_errstr(result));
674 static bool net_spoolss_open_printer_ex(struct rpc_pipe_client *pipe_hnd,
676 const char *printername,
677 uint32_t access_required,
678 const char *username,
679 struct policy_handle *hnd)
682 fstring printername2;
684 fstrcpy(printername2, pipe_hnd->srv_name_slash);
685 fstrcat(printername2, "\\");
686 fstrcat(printername2, printername);
688 DEBUG(10,("connecting to: %s as %s for %s and access: %x\n",
689 pipe_hnd->srv_name_slash, username, printername2, access_required));
692 result = rpccli_spoolss_openprinter_ex(pipe_hnd, mem_ctx,
697 /* be more verbose */
698 if (W_ERROR_V(result) == W_ERROR_V(WERR_ACCESS_DENIED)) {
699 d_fprintf(stderr, "no access to printer [%s] on [%s] for user [%s] granted\n",
700 printername2, pipe_hnd->srv_name_slash, username);
704 if (!W_ERROR_IS_OK(result)) {
705 d_fprintf(stderr, "cannot open printer %s on server %s: %s\n",
706 printername2, pipe_hnd->srv_name_slash, win_errstr(result));
710 DEBUG(2,("got printer handle for printer: %s, server: %s\n",
711 printername2, pipe_hnd->srv_name_slash));
716 static bool net_spoolss_getprinter(struct rpc_pipe_client *pipe_hnd,
718 struct policy_handle *hnd,
720 union spoolss_PrinterInfo *info)
724 /* getprinter call */
725 result = rpccli_spoolss_getprinter(pipe_hnd, mem_ctx,
730 if (!W_ERROR_IS_OK(result)) {
731 printf("cannot get printer-info: %s\n", win_errstr(result));
738 static bool net_spoolss_setprinter(struct rpc_pipe_client *pipe_hnd,
740 struct policy_handle *hnd,
742 union spoolss_PrinterInfo *info)
746 struct spoolss_SetPrinterInfoCtr info_ctr;
747 struct spoolss_DevmodeContainer devmode_ctr;
748 struct sec_desc_buf secdesc_ctr;
750 ZERO_STRUCT(devmode_ctr);
751 ZERO_STRUCT(secdesc_ctr);
753 /* setprinter call */
755 info_ctr.level = level;
758 info_ctr.info.info0 = (struct spoolss_SetPrinterInfo0 *)&info->info0;
761 info_ctr.info.info1 = (struct spoolss_SetPrinterInfo1 *)&info->info1;
764 info_ctr.info.info2 = (struct spoolss_SetPrinterInfo2 *)&info->info2;
767 info_ctr.info.info3 = (struct spoolss_SetPrinterInfo3 *)&info->info3;
770 info_ctr.info.info4 = (struct spoolss_SetPrinterInfo4 *)&info->info4;
773 info_ctr.info.info5 = (struct spoolss_SetPrinterInfo5 *)&info->info5;
776 info_ctr.info.info6 = (struct spoolss_SetPrinterInfo6 *)&info->info6;
779 info_ctr.info.info7 = (struct spoolss_SetPrinterInfo7 *)&info->info7;
783 info_ctr.info.info8 = (struct spoolss_SetPrinterInfo8 *)&info->info8;
786 info_ctr.info.info9 = (struct spoolss_SetPrinterInfo9 *)&info->info9;
793 status = rpccli_spoolss_SetPrinter(pipe_hnd, mem_ctx,
801 if (!W_ERROR_IS_OK(result)) {
802 printf("cannot set printer-info: %s\n", win_errstr(result));
810 static bool net_spoolss_setprinterdata(struct rpc_pipe_client *pipe_hnd,
812 struct policy_handle *hnd,
813 const char *value_name,
814 enum winreg_Type type,
821 /* setprinterdata call */
822 status = rpccli_spoolss_SetPrinterData(pipe_hnd, mem_ctx,
830 if (!W_ERROR_IS_OK(result)) {
831 printf ("unable to set printerdata: %s\n", win_errstr(result));
839 static bool net_spoolss_enumprinterkey(struct rpc_pipe_client *pipe_hnd,
841 struct policy_handle *hnd,
843 const char ***keylist)
847 /* enumprinterkey call */
848 result = rpccli_spoolss_enumprinterkey(pipe_hnd, mem_ctx, hnd, keyname, keylist, 0);
850 if (!W_ERROR_IS_OK(result)) {
851 printf("enumprinterkey failed: %s\n", win_errstr(result));
858 static bool net_spoolss_enumprinterdataex(struct rpc_pipe_client *pipe_hnd,
861 struct policy_handle *hnd,
864 struct spoolss_PrinterEnumValues **info)
868 /* enumprinterdataex call */
869 result = rpccli_spoolss_enumprinterdataex(pipe_hnd, mem_ctx,
876 if (!W_ERROR_IS_OK(result)) {
877 printf("enumprinterdataex failed: %s\n", win_errstr(result));
885 static bool net_spoolss_setprinterdataex(struct rpc_pipe_client *pipe_hnd,
887 struct policy_handle *hnd,
889 REGISTRY_VALUE *value)
894 /* setprinterdataex call */
895 status = rpccli_spoolss_SetPrinterDataEx(pipe_hnd, mem_ctx,
904 if (!W_ERROR_IS_OK(result)) {
905 printf("could not set printerdataex: %s\n", win_errstr(result));
912 static bool net_spoolss_enumforms(struct rpc_pipe_client *pipe_hnd,
914 struct policy_handle *hnd,
917 union spoolss_FormInfo **forms)
922 result = rpccli_spoolss_enumforms(pipe_hnd, mem_ctx,
928 if (!W_ERROR_IS_OK(result)) {
929 printf("could not enum forms: %s\n", win_errstr(result));
936 static bool net_spoolss_enumprinterdrivers (struct rpc_pipe_client *pipe_hnd,
938 uint32_t level, const char *env,
940 union spoolss_DriverInfo **info)
944 /* enumprinterdrivers call */
945 result = rpccli_spoolss_enumprinterdrivers(pipe_hnd, mem_ctx,
946 pipe_hnd->srv_name_slash,
952 if (!W_ERROR_IS_OK(result)) {
953 printf("cannot enum drivers: %s\n", win_errstr(result));
960 static bool net_spoolss_getprinterdriver(struct rpc_pipe_client *pipe_hnd,
962 struct policy_handle *hnd, uint32_t level,
963 const char *env, int version,
964 union spoolss_DriverInfo *info)
967 uint32_t server_major_version;
968 uint32_t server_minor_version;
970 /* getprinterdriver call */
971 result = rpccli_spoolss_getprinterdriver2(pipe_hnd, mem_ctx,
979 &server_major_version,
980 &server_minor_version);
981 if (!W_ERROR_IS_OK(result)) {
982 DEBUG(1,("cannot get driver (for architecture: %s): %s\n",
983 env, win_errstr(result)));
984 if (W_ERROR_V(result) != W_ERROR_V(WERR_UNKNOWN_PRINTER_DRIVER) &&
985 W_ERROR_V(result) != W_ERROR_V(WERR_INVALID_ENVIRONMENT)) {
986 printf("cannot get driver: %s\n", win_errstr(result));
995 static bool net_spoolss_addprinterdriver(struct rpc_pipe_client *pipe_hnd,
996 TALLOC_CTX *mem_ctx, uint32_t level,
997 union spoolss_DriverInfo *info)
1001 struct spoolss_AddDriverInfoCtr info_ctr;
1003 info_ctr.level = level;
1007 info_ctr.info.info2 = (struct spoolss_AddDriverInfo2 *)&info->info2;
1010 info_ctr.info.info3 = (struct spoolss_AddDriverInfo3 *)&info->info3;
1013 printf("unsupported info level: %d\n", level);
1017 /* addprinterdriver call */
1018 status = rpccli_spoolss_AddPrinterDriver(pipe_hnd, mem_ctx,
1019 pipe_hnd->srv_name_slash,
1022 /* be more verbose */
1023 if (W_ERROR_V(result) == W_ERROR_V(WERR_ACCESS_DENIED)) {
1024 printf("You are not allowed to add drivers\n");
1027 if (!W_ERROR_IS_OK(result)) {
1028 printf("cannot add driver: %s\n", win_errstr(result));
1036 * abstraction function to get uint32_t num_printers and PRINTER_INFO_CTR ctr
1037 * for a single printer or for all printers depending on argc/argv
1040 static bool get_printer_info(struct rpc_pipe_client *pipe_hnd,
1041 TALLOC_CTX *mem_ctx,
1045 uint32_t *num_printers,
1046 union spoolss_PrinterInfo **info_p)
1048 struct policy_handle hnd;
1050 /* no arguments given, enumerate all printers */
1053 if (!net_spoolss_enum_printers(pipe_hnd, mem_ctx, NULL,
1054 PRINTER_ENUM_LOCAL|PRINTER_ENUM_SHARED,
1055 level, num_printers, info_p))
1061 /* argument given, get a single printer by name */
1062 if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, argv[0],
1063 MAXIMUM_ALLOWED_ACCESS,
1064 pipe_hnd->auth->user_name,
1068 if (!net_spoolss_getprinter(pipe_hnd, mem_ctx, &hnd, level, *info_p)) {
1069 rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd, NULL);
1073 rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd, NULL);
1078 DEBUG(3,("got %d printers\n", *num_printers));
1085 * List print-queues (including local printers that are not shared)
1087 * All parameters are provided by the run_rpc_command function, except for
1088 * argc, argv which are passed through.
1090 * @param c A net_context structure
1091 * @param domain_sid The domain sid aquired from the remote server
1092 * @param cli A cli_state connected to the server.
1093 * @param mem_ctx Talloc context, destoyed on compleation of the function.
1094 * @param argc Standard main() style argc
1095 * @param argv Standard main() style argv. Initial components are already
1098 * @return Normal NTSTATUS return.
1101 NTSTATUS rpc_printer_list_internals(struct net_context *c,
1102 const DOM_SID *domain_sid,
1103 const char *domain_name,
1104 struct cli_state *cli,
1105 struct rpc_pipe_client *pipe_hnd,
1106 TALLOC_CTX *mem_ctx,
1110 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1111 uint32_t i, num_printers;
1113 const char *printername, *sharename;
1114 union spoolss_PrinterInfo *info;
1116 printf("listing printers\n");
1118 if (!get_printer_info(pipe_hnd, mem_ctx, level, argc, argv, &num_printers, &info))
1121 for (i = 0; i < num_printers; i++) {
1123 /* do some initialization */
1124 printername = info[i].info2.printername;
1125 sharename = info[i].info2.sharename;
1127 if (printername && sharename) {
1128 d_printf("printer %d: %s, shared as: %s\n",
1129 i+1, printername, sharename);
1133 return NT_STATUS_OK;
1137 * List printer-drivers from a server
1139 * All parameters are provided by the run_rpc_command function, except for
1140 * argc, argv which are passed through.
1142 * @param c A net_context structure
1143 * @param domain_sid The domain sid aquired from the remote server
1144 * @param cli A cli_state connected to the server.
1145 * @param mem_ctx Talloc context, destoyed on compleation of the function.
1146 * @param argc Standard main() style argc
1147 * @param argv Standard main() style argv. Initial components are already
1150 * @return Normal NTSTATUS return.
1153 NTSTATUS rpc_printer_driver_list_internals(struct net_context *c,
1154 const DOM_SID *domain_sid,
1155 const char *domain_name,
1156 struct cli_state *cli,
1157 struct rpc_pipe_client *pipe_hnd,
1158 TALLOC_CTX *mem_ctx,
1162 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1165 union spoolss_DriverInfo *info;
1168 printf("listing printer-drivers\n");
1170 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1172 uint32_t num_drivers;
1174 /* enum remote drivers */
1175 if (!net_spoolss_enumprinterdrivers(pipe_hnd, mem_ctx, level,
1176 archi_table[i].long_archi,
1177 &num_drivers, &info)) {
1178 nt_status = NT_STATUS_UNSUCCESSFUL;
1182 if (num_drivers == 0) {
1183 d_printf ("no drivers found on server for architecture: [%s].\n",
1184 archi_table[i].long_archi);
1188 d_printf("got %d printer-drivers for architecture: [%s]\n",
1189 num_drivers, archi_table[i].long_archi);
1192 /* do something for all drivers for architecture */
1193 for (d = 0; d < num_drivers; d++) {
1194 display_print_driver3(&info[d].info3);
1198 nt_status = NT_STATUS_OK;
1206 * Publish print-queues with args-wrapper
1208 * @param cli A cli_state connected to the server.
1209 * @param mem_ctx Talloc context, destoyed on compleation of the function.
1210 * @param argc Standard main() style argc
1211 * @param argv Standard main() style argv. Initial components are already
1215 * @return Normal NTSTATUS return.
1218 static NTSTATUS rpc_printer_publish_internals_args(struct rpc_pipe_client *pipe_hnd,
1219 TALLOC_CTX *mem_ctx,
1224 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1225 uint32_t i, num_printers;
1227 const char *printername, *sharename;
1228 union spoolss_PrinterInfo *info_enum;
1229 union spoolss_PrinterInfo info;
1230 struct spoolss_SetPrinterInfoCtr info_ctr;
1231 struct spoolss_DevmodeContainer devmode_ctr;
1232 struct sec_desc_buf secdesc_ctr;
1233 struct policy_handle hnd;
1235 const char *action_str;
1237 if (!get_printer_info(pipe_hnd, mem_ctx, 2, argc, argv, &num_printers, &info_enum))
1240 for (i = 0; i < num_printers; i++) {
1242 /* do some initialization */
1243 printername = info_enum[i].info2.printername;
1244 sharename = info_enum[i].info2.sharename;
1245 if (!printername || !sharename) {
1249 /* open printer handle */
1250 if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, sharename,
1251 PRINTER_ALL_ACCESS, pipe_hnd->auth->user_name, &hnd))
1254 /* check for existing dst printer */
1255 if (!net_spoolss_getprinter(pipe_hnd, mem_ctx, &hnd, level, &info))
1258 /* check action and set string */
1260 case DSPRINT_PUBLISH:
1261 action_str = "published";
1263 case DSPRINT_UPDATE:
1264 action_str = "updated";
1266 case DSPRINT_UNPUBLISH:
1267 action_str = "unpublished";
1270 action_str = "unknown action";
1271 printf("unkown action: %d\n", action);
1275 info.info7.action = action;
1277 info_ctr.info.info7 = (struct spoolss_SetPrinterInfo7 *)&info.info7;
1279 ZERO_STRUCT(devmode_ctr);
1280 ZERO_STRUCT(secdesc_ctr);
1282 nt_status = rpccli_spoolss_SetPrinter(pipe_hnd, mem_ctx,
1290 if (!W_ERROR_IS_OK(result) && (W_ERROR_V(result) != W_ERROR_V(WERR_IO_PENDING))) {
1291 printf("cannot set printer-info: %s\n", win_errstr(result));
1295 printf("successfully %s printer %s in Active Directory\n", action_str, sharename);
1298 nt_status = NT_STATUS_OK;
1301 if (is_valid_policy_hnd(&hnd))
1302 rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd, NULL);
1307 NTSTATUS rpc_printer_publish_publish_internals(struct net_context *c,
1308 const DOM_SID *domain_sid,
1309 const char *domain_name,
1310 struct cli_state *cli,
1311 struct rpc_pipe_client *pipe_hnd,
1312 TALLOC_CTX *mem_ctx,
1316 return rpc_printer_publish_internals_args(pipe_hnd, mem_ctx, argc, argv, DSPRINT_PUBLISH);
1319 NTSTATUS rpc_printer_publish_unpublish_internals(struct net_context *c,
1320 const DOM_SID *domain_sid,
1321 const char *domain_name,
1322 struct cli_state *cli,
1323 struct rpc_pipe_client *pipe_hnd,
1324 TALLOC_CTX *mem_ctx,
1328 return rpc_printer_publish_internals_args(pipe_hnd, mem_ctx, argc, argv, DSPRINT_UNPUBLISH);
1331 NTSTATUS rpc_printer_publish_update_internals(struct net_context *c,
1332 const DOM_SID *domain_sid,
1333 const char *domain_name,
1334 struct cli_state *cli,
1335 struct rpc_pipe_client *pipe_hnd,
1336 TALLOC_CTX *mem_ctx,
1340 return rpc_printer_publish_internals_args(pipe_hnd, mem_ctx, argc, argv, DSPRINT_UPDATE);
1344 * List print-queues w.r.t. their publishing state
1346 * All parameters are provided by the run_rpc_command function, except for
1347 * argc, argv which are passed through.
1349 * @param c A net_context structure
1350 * @param domain_sid The domain sid aquired from the remote server
1351 * @param cli A cli_state connected to the server.
1352 * @param mem_ctx Talloc context, destoyed on compleation of the function.
1353 * @param argc Standard main() style argc
1354 * @param argv Standard main() style argv. Initial components are already
1357 * @return Normal NTSTATUS return.
1360 NTSTATUS rpc_printer_publish_list_internals(struct net_context *c,
1361 const DOM_SID *domain_sid,
1362 const char *domain_name,
1363 struct cli_state *cli,
1364 struct rpc_pipe_client *pipe_hnd,
1365 TALLOC_CTX *mem_ctx,
1369 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1370 uint32_t i, num_printers;
1372 const char *printername, *sharename;
1373 union spoolss_PrinterInfo *info_enum;
1374 union spoolss_PrinterInfo info;
1375 struct policy_handle hnd;
1378 if (!get_printer_info(pipe_hnd, mem_ctx, 2, argc, argv, &num_printers, &info_enum))
1381 for (i = 0; i < num_printers; i++) {
1383 /* do some initialization */
1384 printername = info_enum[i].info2.printername;
1385 sharename = info_enum[i].info2.sharename;
1387 if (!printername || !sharename) {
1391 /* open printer handle */
1392 if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, sharename,
1393 PRINTER_ALL_ACCESS, cli->user_name, &hnd))
1396 /* check for existing dst printer */
1397 if (!net_spoolss_getprinter(pipe_hnd, mem_ctx, &hnd, level, &info))
1400 if (!info.info7.guid) {
1403 state = info.info7.action;
1405 case DSPRINT_PUBLISH:
1406 printf("printer [%s] is published", sharename);
1408 printf(", guid: %s", info.info7.guid);
1411 case DSPRINT_UNPUBLISH:
1412 printf("printer [%s] is unpublished\n", sharename);
1414 case DSPRINT_UPDATE:
1415 printf("printer [%s] is currently updating\n", sharename);
1418 printf("unkown state: %d\n", state);
1423 nt_status = NT_STATUS_OK;
1426 if (is_valid_policy_hnd(&hnd))
1427 rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd, NULL);
1433 * Migrate Printer-ACLs from a source server to the destination server
1435 * All parameters are provided by the run_rpc_command function, except for
1436 * argc, argv which are passed through.
1438 * @param c A net_context structure
1439 * @param domain_sid The domain sid aquired from the remote server
1440 * @param cli A cli_state connected to the server.
1441 * @param mem_ctx Talloc context, destoyed on compleation of the function.
1442 * @param argc Standard main() style argc
1443 * @param argv Standard main() style argv. Initial components are already
1446 * @return Normal NTSTATUS return.
1449 NTSTATUS rpc_printer_migrate_security_internals(struct net_context *c,
1450 const DOM_SID *domain_sid,
1451 const char *domain_name,
1452 struct cli_state *cli,
1453 struct rpc_pipe_client *pipe_hnd,
1454 TALLOC_CTX *mem_ctx,
1458 /* TODO: what now, info2 or info3 ?
1459 convince jerry that we should add clientside setacls level 3 at least
1461 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1463 uint32_t num_printers;
1465 const char *printername, *sharename;
1466 struct rpc_pipe_client *pipe_hnd_dst = NULL;
1467 struct policy_handle hnd_src, hnd_dst;
1468 union spoolss_PrinterInfo *info_enum;
1469 struct cli_state *cli_dst = NULL;
1470 union spoolss_PrinterInfo info_src, info_dst;
1472 DEBUG(3,("copying printer ACLs\n"));
1474 /* connect destination PI_SPOOLSS */
1475 nt_status = connect_dst_pipe(c, &cli_dst, &pipe_hnd_dst,
1476 &ndr_table_spoolss.syntax_id);
1477 if (!NT_STATUS_IS_OK(nt_status))
1481 /* enum source printers */
1482 if (!get_printer_info(pipe_hnd, mem_ctx, level, argc, argv, &num_printers, &info_enum)) {
1483 nt_status = NT_STATUS_UNSUCCESSFUL;
1487 if (!num_printers) {
1488 printf ("no printers found on server.\n");
1489 nt_status = NT_STATUS_OK;
1493 /* do something for all printers */
1494 for (i = 0; i < num_printers; i++) {
1496 /* do some initialization */
1497 printername = info_enum[i].info2.printername;
1498 sharename = info_enum[i].info2.sharename;
1500 if (!printername || !sharename) {
1501 nt_status = NT_STATUS_UNSUCCESSFUL;
1505 /* we can reset NT_STATUS here because we do not
1506 get any real NT_STATUS-codes anymore from now on */
1507 nt_status = NT_STATUS_UNSUCCESSFUL;
1509 d_printf("migrating printer ACLs for: [%s] / [%s]\n",
1510 printername, sharename);
1512 /* according to msdn you have specify these access-rights
1513 to see the security descriptor
1514 - READ_CONTROL (DACL)
1515 - ACCESS_SYSTEM_SECURITY (SACL)
1518 /* open src printer handle */
1519 if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, sharename,
1520 MAXIMUM_ALLOWED_ACCESS, cli->user_name, &hnd_src))
1523 /* open dst printer handle */
1524 if (!net_spoolss_open_printer_ex(pipe_hnd_dst, mem_ctx, sharename,
1525 PRINTER_ALL_ACCESS, cli_dst->user_name, &hnd_dst))
1528 /* check for existing dst printer */
1529 if (!net_spoolss_getprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, level, &info_dst))
1532 /* check for existing src printer */
1533 if (!net_spoolss_getprinter(pipe_hnd, mem_ctx, &hnd_src, 3, &info_src))
1536 /* Copy Security Descriptor */
1538 /* copy secdesc (info level 2) */
1539 info_dst.info2.devmode = NULL;
1540 info_dst.info2.secdesc = dup_sec_desc(mem_ctx, info_src.info3.secdesc);
1543 display_sec_desc(info_dst.info2.secdesc);
1545 if (!net_spoolss_setprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, 2, &info_dst))
1548 DEBUGADD(1,("\tSetPrinter of SECDESC succeeded\n"));
1551 /* close printer handles here */
1552 if (is_valid_policy_hnd(&hnd_src)) {
1553 rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd_src, NULL);
1556 if (is_valid_policy_hnd(&hnd_dst)) {
1557 rpccli_spoolss_ClosePrinter(pipe_hnd_dst, mem_ctx, &hnd_dst, NULL);
1562 nt_status = NT_STATUS_OK;
1566 if (is_valid_policy_hnd(&hnd_src)) {
1567 rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd_src, NULL);
1570 if (is_valid_policy_hnd(&hnd_dst)) {
1571 rpccli_spoolss_ClosePrinter(pipe_hnd_dst, mem_ctx, &hnd_dst, NULL);
1575 cli_shutdown(cli_dst);
1581 * Migrate printer-forms from a src server to the dst server
1583 * All parameters are provided by the run_rpc_command function, except for
1584 * argc, argv which are passed through.
1586 * @param c A net_context structure
1587 * @param domain_sid The domain sid aquired from the remote server
1588 * @param cli A cli_state connected to the server.
1589 * @param mem_ctx Talloc context, destoyed on compleation of the function.
1590 * @param argc Standard main() style argc
1591 * @param argv Standard main() style argv. Initial components are already
1594 * @return Normal NTSTATUS return.
1597 NTSTATUS rpc_printer_migrate_forms_internals(struct net_context *c,
1598 const DOM_SID *domain_sid,
1599 const char *domain_name,
1600 struct cli_state *cli,
1601 struct rpc_pipe_client *pipe_hnd,
1602 TALLOC_CTX *mem_ctx,
1606 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1609 uint32_t num_printers;
1611 const char *printername, *sharename;
1612 struct rpc_pipe_client *pipe_hnd_dst = NULL;
1613 struct policy_handle hnd_src, hnd_dst;
1614 union spoolss_PrinterInfo *info_enum;
1615 union spoolss_PrinterInfo info_dst;
1617 union spoolss_FormInfo *forms;
1618 struct cli_state *cli_dst = NULL;
1620 DEBUG(3,("copying forms\n"));
1622 /* connect destination PI_SPOOLSS */
1623 nt_status = connect_dst_pipe(c, &cli_dst, &pipe_hnd_dst,
1624 &ndr_table_spoolss.syntax_id);
1625 if (!NT_STATUS_IS_OK(nt_status))
1628 /* enum src printers */
1629 if (!get_printer_info(pipe_hnd, mem_ctx, 2, argc, argv, &num_printers, &info_enum)) {
1630 nt_status = NT_STATUS_UNSUCCESSFUL;
1634 if (!num_printers) {
1635 printf ("no printers found on server.\n");
1636 nt_status = NT_STATUS_OK;
1640 /* do something for all printers */
1641 for (i = 0; i < num_printers; i++) {
1643 /* do some initialization */
1644 printername = info_enum[i].info2.printername;
1645 sharename = info_enum[i].info2.sharename;
1647 if (!printername || !sharename) {
1648 nt_status = NT_STATUS_UNSUCCESSFUL;
1651 /* we can reset NT_STATUS here because we do not
1652 get any real NT_STATUS-codes anymore from now on */
1653 nt_status = NT_STATUS_UNSUCCESSFUL;
1655 d_printf("migrating printer forms for: [%s] / [%s]\n",
1656 printername, sharename);
1659 /* open src printer handle */
1660 if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, sharename,
1661 MAXIMUM_ALLOWED_ACCESS, cli->user_name, &hnd_src))
1664 /* open dst printer handle */
1665 if (!net_spoolss_open_printer_ex(pipe_hnd_dst, mem_ctx, sharename,
1666 PRINTER_ALL_ACCESS, cli->user_name, &hnd_dst))
1669 /* check for existing dst printer */
1670 if (!net_spoolss_getprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, level, &info_dst))
1673 /* finally migrate forms */
1674 if (!net_spoolss_enumforms(pipe_hnd, mem_ctx, &hnd_src, level, &num_forms, &forms))
1677 DEBUG(1,("got %d forms for printer\n", num_forms));
1680 for (f = 0; f < num_forms; f++) {
1682 union spoolss_AddFormInfo info;
1685 /* only migrate FORM_PRINTER types, according to jerry
1686 FORM_BUILTIN-types are hard-coded in samba */
1687 if (forms[f].info1.flags != SPOOLSS_FORM_PRINTER)
1691 d_printf("\tmigrating form # %d [%s] of type [%d]\n",
1692 f, forms[f].info1.form_name,
1693 forms[f].info1.flags);
1695 info.info1 = (struct spoolss_AddFormInfo1 *)&forms[f].info1;
1697 /* FIXME: there might be something wrong with samba's
1699 status = rpccli_spoolss_AddForm(pipe_hnd_dst, mem_ctx,
1704 if (!W_ERROR_IS_OK(result)) {
1705 d_printf("\tAddForm form %d: [%s] refused.\n",
1706 f, forms[f].info1.form_name);
1710 DEBUGADD(1,("\tAddForm of [%s] succeeded\n",
1711 forms[f].info1.form_name));
1715 /* close printer handles here */
1716 if (is_valid_policy_hnd(&hnd_src)) {
1717 rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd_src, NULL);
1720 if (is_valid_policy_hnd(&hnd_dst)) {
1721 rpccli_spoolss_ClosePrinter(pipe_hnd_dst, mem_ctx, &hnd_dst, NULL);
1725 nt_status = NT_STATUS_OK;
1729 if (is_valid_policy_hnd(&hnd_src))
1730 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);
1736 cli_shutdown(cli_dst);
1742 * Migrate printer-drivers from a src server to the dst server
1744 * All parameters are provided by the run_rpc_command function, except for
1745 * argc, argv which are passed through.
1747 * @param c A net_context structure
1748 * @param domain_sid The domain sid aquired from the remote server
1749 * @param cli A cli_state connected to the server.
1750 * @param mem_ctx Talloc context, destoyed on compleation of the function.
1751 * @param argc Standard main() style argc
1752 * @param argv Standard main() style argv. Initial components are already
1755 * @return Normal NTSTATUS return.
1758 NTSTATUS rpc_printer_migrate_drivers_internals(struct net_context *c,
1759 const DOM_SID *domain_sid,
1760 const char *domain_name,
1761 struct cli_state *cli,
1762 struct rpc_pipe_client *pipe_hnd,
1763 TALLOC_CTX *mem_ctx,
1767 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1769 uint32_t num_printers;
1771 const char *printername, *sharename;
1772 bool got_src_driver_share = false;
1773 bool got_dst_driver_share = false;
1774 struct rpc_pipe_client *pipe_hnd_dst = NULL;
1775 struct policy_handle hnd_src, hnd_dst;
1776 union spoolss_DriverInfo drv_info_src;
1777 union spoolss_PrinterInfo *info_enum;
1778 union spoolss_PrinterInfo info_dst;
1779 struct cli_state *cli_dst = NULL;
1780 struct cli_state *cli_share_src = NULL;
1781 struct cli_state *cli_share_dst = NULL;
1782 const char *drivername = NULL;
1784 DEBUG(3,("copying printer-drivers\n"));
1786 nt_status = connect_dst_pipe(c, &cli_dst, &pipe_hnd_dst,
1787 &ndr_table_spoolss.syntax_id);
1788 if (!NT_STATUS_IS_OK(nt_status))
1791 /* open print$-share on the src server */
1792 nt_status = connect_to_service(c, &cli_share_src, &cli->dest_ss,
1793 cli->desthost, "print$", "A:");
1794 if (!NT_STATUS_IS_OK(nt_status))
1797 got_src_driver_share = true;
1800 /* open print$-share on the dst server */
1801 nt_status = connect_to_service(c, &cli_share_dst, &cli_dst->dest_ss,
1802 cli_dst->desthost, "print$", "A:");
1803 if (!NT_STATUS_IS_OK(nt_status))
1806 got_dst_driver_share = true;
1809 /* enum src printers */
1810 if (!get_printer_info(pipe_hnd, mem_ctx, 2, argc, argv, &num_printers, &info_enum)) {
1811 nt_status = NT_STATUS_UNSUCCESSFUL;
1815 if (num_printers == 0) {
1816 printf ("no printers found on server.\n");
1817 nt_status = NT_STATUS_OK;
1822 /* do something for all printers */
1823 for (p = 0; p < num_printers; p++) {
1825 /* do some initialization */
1826 printername = info_enum[p].info2.printername;
1827 sharename = info_enum[p].info2.sharename;
1829 if (!printername || !sharename) {
1830 nt_status = NT_STATUS_UNSUCCESSFUL;
1834 /* we can reset NT_STATUS here because we do not
1835 get any real NT_STATUS-codes anymore from now on */
1836 nt_status = NT_STATUS_UNSUCCESSFUL;
1838 d_printf("migrating printer driver for: [%s] / [%s]\n",
1839 printername, sharename);
1841 /* open dst printer handle */
1842 if (!net_spoolss_open_printer_ex(pipe_hnd_dst, mem_ctx, sharename,
1843 PRINTER_ALL_ACCESS, cli->user_name, &hnd_dst))
1846 /* check for existing dst printer */
1847 if (!net_spoolss_getprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, 2, &info_dst))
1851 /* open src printer handle */
1852 if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, sharename,
1853 MAXIMUM_ALLOWED_ACCESS,
1854 pipe_hnd->auth->user_name,
1858 /* in a first step call getdriver for each shared printer (per arch)
1859 to get a list of all files that have to be copied */
1861 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1864 if (!net_spoolss_getprinterdriver(pipe_hnd, mem_ctx, &hnd_src,
1865 level, archi_table[i].long_archi,
1866 archi_table[i].version, &drv_info_src))
1869 drivername = drv_info_src.info3.driver_name;
1872 display_print_driver3(&drv_info_src.info3);
1874 /* check arch dir */
1875 nt_status = check_arch_dir(cli_share_dst, archi_table[i].short_archi);
1876 if (!NT_STATUS_IS_OK(nt_status))
1880 /* copy driver-files */
1881 nt_status = copy_print_driver_3(c, mem_ctx, cli_share_src, cli_share_dst,
1882 archi_table[i].short_archi,
1883 &drv_info_src.info3);
1884 if (!NT_STATUS_IS_OK(nt_status))
1889 if (!net_spoolss_addprinterdriver(pipe_hnd_dst, mem_ctx, level, &drv_info_src)) {
1890 nt_status = NT_STATUS_UNSUCCESSFUL;
1894 DEBUGADD(1,("Sucessfully added driver [%s] for printer [%s]\n",
1895 drivername, printername));
1899 if (!drivername || strlen(drivername) == 0) {
1900 DEBUGADD(1,("Did not get driver for printer %s\n",
1906 info_dst.info2.drivername = drivername;
1908 if (!net_spoolss_setprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, 2, &info_dst)) {
1909 nt_status = NT_STATUS_UNSUCCESSFUL;
1913 DEBUGADD(1,("Sucessfully set driver %s for printer %s\n",
1914 drivername, printername));
1917 if (is_valid_policy_hnd(&hnd_dst)) {
1918 rpccli_spoolss_ClosePrinter(pipe_hnd_dst, mem_ctx, &hnd_dst, NULL);
1922 if (is_valid_policy_hnd(&hnd_src)) {
1923 rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd_src, NULL);
1927 nt_status = NT_STATUS_OK;
1931 if (is_valid_policy_hnd(&hnd_src))
1932 rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd_src, NULL);
1934 if (is_valid_policy_hnd(&hnd_dst))
1935 rpccli_spoolss_ClosePrinter(pipe_hnd_dst, mem_ctx, &hnd_dst, NULL);
1938 cli_shutdown(cli_dst);
1941 if (got_src_driver_share)
1942 cli_shutdown(cli_share_src);
1944 if (got_dst_driver_share)
1945 cli_shutdown(cli_share_dst);
1952 * Migrate printer-queues from a src to the dst server
1953 * (requires a working "addprinter command" to be installed for the local smbd)
1955 * All parameters are provided by the run_rpc_command function, except for
1956 * argc, argv which are passed through.
1958 * @param c A net_context structure
1959 * @param domain_sid The domain sid aquired from the remote server
1960 * @param cli A cli_state connected to the server.
1961 * @param mem_ctx Talloc context, destoyed on compleation of the function.
1962 * @param argc Standard main() style argc
1963 * @param argv Standard main() style argv. Initial components are already
1966 * @return Normal NTSTATUS return.
1969 NTSTATUS rpc_printer_migrate_printers_internals(struct net_context *c,
1970 const DOM_SID *domain_sid,
1971 const char *domain_name,
1972 struct cli_state *cli,
1973 struct rpc_pipe_client *pipe_hnd,
1974 TALLOC_CTX *mem_ctx,
1979 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1980 uint32_t i = 0, num_printers;
1982 union spoolss_PrinterInfo info_dst, info_src;
1983 union spoolss_PrinterInfo *info_enum;
1984 struct cli_state *cli_dst = NULL;
1985 struct policy_handle hnd_dst, hnd_src;
1986 const char *printername, *sharename;
1987 struct rpc_pipe_client *pipe_hnd_dst = NULL;
1988 struct spoolss_SetPrinterInfoCtr info_ctr;
1990 DEBUG(3,("copying printers\n"));
1992 /* connect destination PI_SPOOLSS */
1993 nt_status = connect_dst_pipe(c, &cli_dst, &pipe_hnd_dst,
1994 &ndr_table_spoolss.syntax_id);
1995 if (!NT_STATUS_IS_OK(nt_status))
1999 if (!get_printer_info(pipe_hnd, mem_ctx, level, argc, argv, &num_printers, &info_enum)) {
2000 nt_status = NT_STATUS_UNSUCCESSFUL;
2004 if (!num_printers) {
2005 printf ("no printers found on server.\n");
2006 nt_status = NT_STATUS_OK;
2010 /* do something for all printers */
2011 for (i = 0; i < num_printers; i++) {
2013 /* do some initialization */
2014 printername = info_enum[i].info2.printername;
2015 sharename = info_enum[i].info2.sharename;
2017 if (!printername || !sharename) {
2018 nt_status = NT_STATUS_UNSUCCESSFUL;
2021 /* we can reset NT_STATUS here because we do not
2022 get any real NT_STATUS-codes anymore from now on */
2023 nt_status = NT_STATUS_UNSUCCESSFUL;
2025 d_printf("migrating printer queue for: [%s] / [%s]\n",
2026 printername, sharename);
2028 /* open dst printer handle */
2029 if (!net_spoolss_open_printer_ex(pipe_hnd_dst, mem_ctx, sharename,
2030 PRINTER_ALL_ACCESS, cli->user_name, &hnd_dst)) {
2032 DEBUG(1,("could not open printer: %s\n", sharename));
2035 /* check for existing dst printer */
2036 if (!net_spoolss_getprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, level, &info_dst)) {
2037 printf ("could not get printer, creating printer.\n");
2039 DEBUG(1,("printer already exists: %s\n", sharename));
2040 /* close printer handle here - dst only, not got src yet. */
2041 if (is_valid_policy_hnd(&hnd_dst)) {
2042 rpccli_spoolss_ClosePrinter(pipe_hnd_dst, mem_ctx, &hnd_dst, NULL);
2047 /* now get again src printer ctr via getprinter,
2048 we first need a handle for that */
2050 /* open src printer handle */
2051 if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, sharename,
2052 MAXIMUM_ALLOWED_ACCESS, cli->user_name, &hnd_src))
2055 /* getprinter on the src server */
2056 if (!net_spoolss_getprinter(pipe_hnd, mem_ctx, &hnd_src, level, &info_src))
2059 /* copy each src printer to a dst printer 1:1,
2060 maybe some values have to be changed though */
2061 d_printf("creating printer: %s\n", printername);
2063 info_ctr.level = level;
2064 info_ctr.info.info2 = (struct spoolss_SetPrinterInfo2 *)&info_src.info2;
2066 result = rpccli_spoolss_addprinterex(pipe_hnd_dst,
2070 if (W_ERROR_IS_OK(result))
2071 d_printf ("printer [%s] successfully added.\n", printername);
2072 else if (W_ERROR_V(result) == W_ERROR_V(WERR_PRINTER_ALREADY_EXISTS))
2073 d_fprintf (stderr, "printer [%s] already exists.\n", printername);
2075 d_fprintf (stderr, "could not create printer [%s]\n", printername);
2079 /* close printer handles here */
2080 if (is_valid_policy_hnd(&hnd_src)) {
2081 rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd_src, NULL);
2084 if (is_valid_policy_hnd(&hnd_dst)) {
2085 rpccli_spoolss_ClosePrinter(pipe_hnd_dst, mem_ctx, &hnd_dst, NULL);
2089 nt_status = NT_STATUS_OK;
2092 if (is_valid_policy_hnd(&hnd_src))
2093 rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd_src, NULL);
2095 if (is_valid_policy_hnd(&hnd_dst))
2096 rpccli_spoolss_ClosePrinter(pipe_hnd_dst, mem_ctx, &hnd_dst, NULL);
2099 cli_shutdown(cli_dst);
2105 * Migrate Printer-Settings from a src server to the dst server
2106 * (for this to work, printers and drivers already have to be migrated earlier)
2108 * All parameters are provided by the run_rpc_command function, except for
2109 * argc, argv which are passed through.
2111 * @param c A net_context structure
2112 * @param domain_sid The domain sid aquired from the remote server
2113 * @param cli A cli_state connected to the server.
2114 * @param mem_ctx Talloc context, destoyed on compleation of the function.
2115 * @param argc Standard main() style argc
2116 * @param argv Standard main() style argv. Initial components are already
2119 * @return Normal NTSTATUS return.
2122 NTSTATUS rpc_printer_migrate_settings_internals(struct net_context *c,
2123 const DOM_SID *domain_sid,
2124 const char *domain_name,
2125 struct cli_state *cli,
2126 struct rpc_pipe_client *pipe_hnd,
2127 TALLOC_CTX *mem_ctx,
2132 /* FIXME: Here the nightmare begins */
2135 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
2136 uint32_t i = 0, p = 0, j = 0;
2137 uint32_t num_printers;
2139 const char *printername, *sharename;
2140 struct rpc_pipe_client *pipe_hnd_dst = NULL;
2141 struct policy_handle hnd_src, hnd_dst;
2142 union spoolss_PrinterInfo *info_enum;
2143 union spoolss_PrinterInfo info_dst_publish;
2144 union spoolss_PrinterInfo info_dst;
2145 struct cli_state *cli_dst = NULL;
2146 char *devicename = NULL, *unc_name = NULL, *url = NULL;
2147 const char *longname;
2148 const char **keylist = NULL;
2151 ZERO_STRUCT(info_dst_publish);
2153 DEBUG(3,("copying printer settings\n"));
2155 /* connect destination PI_SPOOLSS */
2156 nt_status = connect_dst_pipe(c, &cli_dst, &pipe_hnd_dst,
2157 &ndr_table_spoolss.syntax_id);
2158 if (!NT_STATUS_IS_OK(nt_status))
2161 /* enum src printers */
2162 if (!get_printer_info(pipe_hnd, mem_ctx, level, argc, argv, &num_printers, &info_enum)) {
2163 nt_status = NT_STATUS_UNSUCCESSFUL;
2167 if (!num_printers) {
2168 printf ("no printers found on server.\n");
2169 nt_status = NT_STATUS_OK;
2174 /* needed for dns-strings in regkeys */
2175 longname = get_mydnsfullname();
2177 nt_status = NT_STATUS_UNSUCCESSFUL;
2181 /* do something for all printers */
2182 for (i = 0; i < num_printers; i++) {
2184 uint32_t value_offered = 0, value_needed;
2185 uint32_t data_offered = 0, data_needed;
2186 enum winreg_Type type;
2187 uint8_t *buffer = NULL;
2188 const char *value_name = NULL;
2190 /* do some initialization */
2191 printername = info_enum[i].info2.printername;
2192 sharename = info_enum[i].info2.sharename;
2194 if (!printername || !sharename) {
2195 nt_status = NT_STATUS_UNSUCCESSFUL;
2198 /* we can reset NT_STATUS here because we do not
2199 get any real NT_STATUS-codes anymore from now on */
2200 nt_status = NT_STATUS_UNSUCCESSFUL;
2202 d_printf("migrating printer settings for: [%s] / [%s]\n",
2203 printername, sharename);
2206 /* open src printer handle */
2207 if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, sharename,
2208 MAXIMUM_ALLOWED_ACCESS, cli->user_name, &hnd_src))
2211 /* open dst printer handle */
2212 if (!net_spoolss_open_printer_ex(pipe_hnd_dst, mem_ctx, sharename,
2213 PRINTER_ALL_ACCESS, cli_dst->user_name, &hnd_dst))
2216 /* check for existing dst printer */
2217 if (!net_spoolss_getprinter(pipe_hnd_dst, mem_ctx, &hnd_dst,
2222 /* STEP 1: COPY DEVICE-MODE and other
2223 PRINTER_INFO_2-attributes
2226 info_dst.info2 = info_enum[i].info2;
2228 /* why is the port always disconnected when the printer
2229 is correctly installed (incl. driver ???) */
2230 info_dst.info2.portname = SAMBA_PRINTER_PORT_NAME;
2232 /* check if printer is published */
2233 if (info_enum[i].info2.attributes & PRINTER_ATTRIBUTE_PUBLISHED) {
2235 /* check for existing dst printer */
2236 if (!net_spoolss_getprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, 7, &info_dst_publish))
2239 info_dst_publish.info7.action = DSPRINT_PUBLISH;
2241 /* ignore false from setprinter due to WERR_IO_PENDING */
2242 net_spoolss_setprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, 7, &info_dst_publish);
2244 DEBUG(3,("republished printer\n"));
2247 if (info_enum[i].info2.devmode != NULL) {
2249 /* copy devmode (info level 2) */
2250 info_dst.info2.devmode = info_enum[i].info2.devmode;
2252 /* do not copy security descriptor (we have another
2253 * command for that) */
2254 info_dst.info2.secdesc = NULL;
2257 info_dst.info2.devmode.devicename =
2258 talloc_asprintf(mem_ctx, "\\\\%s\\%s",
2259 longname, printername);
2260 if (!info_dst.info2.devmode.devicename) {
2261 nt_status = NT_STATUS_NO_MEMORY;
2265 if (!net_spoolss_setprinter(pipe_hnd_dst, mem_ctx, &hnd_dst,
2269 DEBUGADD(1,("\tSetPrinter of DEVICEMODE succeeded\n"));
2272 /* STEP 2: COPY REGISTRY VALUES */
2274 /* please keep in mind that samba parse_spools gives horribly
2275 crippled results when used to rpccli_spoolss_enumprinterdataex
2276 a win2k3-server. (Bugzilla #1851)
2277 FIXME: IIRC I've seen it too on a win2k-server
2280 /* enumerate data on src handle */
2281 nt_status = rpccli_spoolss_EnumPrinterData(pipe_hnd, mem_ctx,
2293 data_offered = data_needed;
2294 value_offered = value_needed;
2295 buffer = talloc_zero_array(mem_ctx, uint8_t, data_needed);
2296 value_name = talloc_zero_array(mem_ctx, char, value_needed);
2298 /* loop for all printerdata of "PrinterDriverData" */
2299 while (NT_STATUS_IS_OK(nt_status) && W_ERROR_IS_OK(result)) {
2301 nt_status = rpccli_spoolss_EnumPrinterData(pipe_hnd, mem_ctx,
2312 /* loop for all reg_keys */
2313 if (NT_STATUS_IS_OK(nt_status) && W_ERROR_IS_OK(result)) {
2318 if (c->opt_verbose) {
2319 fstrcpy(v.valuename, value_name);
2321 v.size = data_offered;
2323 display_reg_value(SPOOL_PRINTERDATA_KEY, v);
2327 if (!net_spoolss_setprinterdata(pipe_hnd_dst, mem_ctx,
2328 &hnd_dst, value_name,
2329 type, buffer, data_offered))
2332 DEBUGADD(1,("\tSetPrinterData of [%s] succeeded\n",
2337 /* STEP 3: COPY SUBKEY VALUES */
2339 /* here we need to enum all printer_keys and then work
2340 on the result with enum_printer_key_ex. nt4 does not
2341 respond to enumprinterkey, win2k does, so continue
2342 in case of an error */
2344 if (!net_spoolss_enumprinterkey(pipe_hnd, mem_ctx, &hnd_src, "", &keylist)) {
2345 printf("got no key-data\n");
2350 /* work on a list of printer keys
2351 each key has to be enumerated to get all required
2352 information. information is then set via setprinterdataex-calls */
2354 if (keylist == NULL)
2357 for (i=0; keylist && keylist[i] != NULL; i++) {
2359 const char *subkey = keylist[i];
2361 struct spoolss_PrinterEnumValues *info;
2363 /* enumerate all src subkeys */
2364 if (!net_spoolss_enumprinterdataex(pipe_hnd, mem_ctx, 0,
2370 for (j=0; j < count; j++) {
2372 REGISTRY_VALUE value;
2375 /* although samba replies with sane data in most cases we
2376 should try to avoid writing wrong registry data */
2378 if (strequal(info[j].value_name, SPOOL_REG_PORTNAME) ||
2379 strequal(info[j].value_name, SPOOL_REG_UNCNAME) ||
2380 strequal(info[j].value_name, SPOOL_REG_URL) ||
2381 strequal(info[j].value_name, SPOOL_REG_SHORTSERVERNAME) ||
2382 strequal(info[j].value_name, SPOOL_REG_SERVERNAME)) {
2384 if (strequal(info[j].value_name, SPOOL_REG_PORTNAME)) {
2386 /* although windows uses a multi-sz, we use a sz */
2387 init_unistr2(&data, SAMBA_PRINTER_PORT_NAME, UNI_STR_TERMINATE);
2388 fstrcpy(value.valuename, SPOOL_REG_PORTNAME);
2391 if (strequal(info[j].value_name, SPOOL_REG_UNCNAME)) {
2393 if (asprintf(&unc_name, "\\\\%s\\%s", longname, sharename) < 0) {
2394 nt_status = NT_STATUS_NO_MEMORY;
2397 init_unistr2(&data, unc_name, UNI_STR_TERMINATE);
2398 fstrcpy(value.valuename, SPOOL_REG_UNCNAME);
2401 if (strequal(info[j].value_name, SPOOL_REG_URL)) {
2406 /* FIXME: should we really do that ??? */
2407 if (asprintf(&url, "http://%s:631/printers/%s", longname, sharename) < 0) {
2408 nt_status = NT_STATUS_NO_MEMORY;
2411 init_unistr2(&data, url, UNI_STR_TERMINATE);
2412 fstrcpy(value.valuename, SPOOL_REG_URL);
2416 if (strequal(info[j].value_name, SPOOL_REG_SERVERNAME)) {
2418 init_unistr2(&data, longname, UNI_STR_TERMINATE);
2419 fstrcpy(value.valuename, SPOOL_REG_SERVERNAME);
2422 if (strequal(info[j].value_name, SPOOL_REG_SHORTSERVERNAME)) {
2424 init_unistr2(&data, global_myname(), UNI_STR_TERMINATE);
2425 fstrcpy(value.valuename, SPOOL_REG_SHORTSERVERNAME);
2428 value.type = REG_SZ;
2429 value.size = data.uni_str_len * 2;
2431 value.data_p = (uint8_t *)TALLOC_MEMDUP(mem_ctx, data.buffer, value.size);
2433 value.data_p = NULL;
2437 display_reg_value(subkey, value);
2439 /* here we have to set all subkeys on the dst server */
2440 if (!net_spoolss_setprinterdataex(pipe_hnd_dst, mem_ctx, &hnd_dst,
2449 result = push_spoolss_PrinterData(mem_ctx, &blob,
2452 if (!W_ERROR_IS_OK(result)) {
2456 fstrcpy(v.valuename, info[j].value_name);
2457 v.type = info[j].type;
2458 v.data_p = blob.data;
2459 v.size = blob.length;
2461 if (c->opt_verbose) {
2462 display_reg_value(subkey, v);
2465 /* here we have to set all subkeys on the dst server */
2466 if (!net_spoolss_setprinterdataex(pipe_hnd_dst, mem_ctx, &hnd_dst,
2473 DEBUGADD(1,("\tSetPrinterDataEx of key [%s\\%s] succeeded\n",
2474 subkey, info[j].value_name));
2479 TALLOC_FREE(keylist);
2481 /* close printer handles here */
2482 if (is_valid_policy_hnd(&hnd_src)) {
2483 rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd_src, NULL);
2486 if (is_valid_policy_hnd(&hnd_dst)) {
2487 rpccli_spoolss_ClosePrinter(pipe_hnd_dst, mem_ctx, &hnd_dst, NULL);
2492 nt_status = NT_STATUS_OK;
2495 SAFE_FREE(devicename);
2497 SAFE_FREE(unc_name);
2499 if (is_valid_policy_hnd(&hnd_src))
2500 rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd_src, NULL);
2502 if (is_valid_policy_hnd(&hnd_dst))
2503 rpccli_spoolss_ClosePrinter(pipe_hnd_dst, mem_ctx, &hnd_dst, NULL);
2506 cli_shutdown(cli_dst);