release-scripts: add build-htmlman-nogit
[Samba/bb.git] / source3 / utils / net_rpc_printer.c
blob470d61a751fe4db472b89b6a4b0c66eef127687e
1 /*
2 Samba Unix/Linux SMB client library
3 Distributed SMB/CIFS Server Management Utility
4 Copyright (C) 2004,2009 Guenther Deschner (gd@samba.org)
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #include "includes.h"
20 #include "utils/net.h"
21 #include "../librpc/gen_ndr/cli_spoolss.h"
22 #include "rpc_client/cli_spoolss.h"
23 #include "rpc_client/init_spoolss.h"
24 #include "nt_printing.h"
25 #include "registry.h"
26 #include "registry/reg_objects.h"
27 #include "../libcli/security/security.h"
29 /* support itanium as well */
30 static const struct print_architecture_table_node archi_table[]= {
32 {"Windows 4.0", "WIN40", 0 },
33 {"Windows NT x86", "W32X86", 2 },
34 {"Windows NT x86", "W32X86", 3 },
35 {"Windows NT R4000", "W32MIPS", 2 },
36 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
37 {"Windows NT PowerPC", "W32PPC", 2 },
38 {"Windows IA64", "IA64", 3 },
39 {"Windows x64", "x64", 3 },
40 {NULL, "", -1 }
44 /**
45 * This display-printdriver-functions was borrowed from rpcclient/cmd_spoolss.c.
46 * It is here for debugging purpose and should be removed later on.
47 **/
49 /****************************************************************************
50 Printer info level 3 display function.
51 ****************************************************************************/
53 static void display_print_driver3(struct spoolss_DriverInfo3 *r)
55 int i;
57 if (!r) {
58 return;
61 printf(_("Printer Driver Info 3:\n"));
62 printf(_("\tVersion: [%x]\n"), r->version);
63 printf(_("\tDriver Name: [%s]\n"), r->driver_name);
64 printf(_("\tArchitecture: [%s]\n"), r->architecture);
65 printf(_("\tDriver Path: [%s]\n"), r->driver_path);
66 printf(_("\tDatafile: [%s]\n"), r->data_file);
67 printf(_("\tConfigfile: [%s]\n\n"), r->config_file);
68 printf(_("\tHelpfile: [%s]\n\n"), r->help_file);
70 for (i=0; r->dependent_files[i] != NULL; i++) {
71 printf(_("\tDependentfiles: [%s]\n"), r->dependent_files[i]);
74 printf("\n");
76 printf(_("\tMonitorname: [%s]\n"), r->monitor_name);
77 printf(_("\tDefaultdatatype: [%s]\n\n"), r->default_datatype);
80 static void display_reg_value(const char *subkey, struct regval_blob *value)
82 const char *text;
83 DATA_BLOB blob;
85 switch(regval_type(value)) {
86 case REG_DWORD:
87 d_printf(_("\t[%s:%s]: REG_DWORD: 0x%08x\n"), subkey,
88 regval_name(value), *((uint32_t *) regval_data_p(value)));
89 break;
91 case REG_SZ:
92 blob = data_blob_const(regval_data_p(value), regval_size(value));
93 pull_reg_sz(talloc_tos(), &blob, &text);
94 if (!text) {
95 break;
97 d_printf(_("\t[%s:%s]: REG_SZ: %s\n"), subkey, regval_name(value),
98 text);
99 break;
101 case REG_BINARY:
102 d_printf(_("\t[%s:%s]: REG_BINARY: unknown length value not "
103 "displayed\n"),
104 subkey, regval_name(value));
105 break;
107 case REG_MULTI_SZ: {
108 uint32_t i;
109 const char **values;
110 blob = data_blob_const(regval_data_p(value), regval_size(value));
112 if (!pull_reg_multi_sz(NULL, &blob, &values)) {
113 d_printf("pull_reg_multi_sz failed\n");
114 break;
117 printf("%s: REG_MULTI_SZ: \n", regval_name(value));
118 for (i=0; values[i] != NULL; i++) {
119 d_printf("%s\n", values[i]);
121 TALLOC_FREE(values);
122 break;
125 default:
126 d_printf(_("\t%s: unknown type %d\n"), regval_name(value),
127 regval_type(value));
133 * Copies ACLs, DOS-attributes and timestamps from one
134 * file or directory from one connected share to another connected share
136 * @param c A net_context structure
137 * @param mem_ctx A talloc-context
138 * @param cli_share_src A connected cli_state
139 * @param cli_share_dst A connected cli_state
140 * @param src_file The source file-name
141 * @param dst_file The destination file-name
142 * @param copy_acls Whether to copy acls
143 * @param copy_attrs Whether to copy DOS attributes
144 * @param copy_timestamps Whether to preserve timestamps
145 * @param is_file Whether this file is a file or a dir
147 * @return Normal NTSTATUS return.
150 NTSTATUS net_copy_fileattr(struct net_context *c,
151 TALLOC_CTX *mem_ctx,
152 struct cli_state *cli_share_src,
153 struct cli_state *cli_share_dst,
154 const char *src_name, const char *dst_name,
155 bool copy_acls, bool copy_attrs,
156 bool copy_timestamps, bool is_file)
158 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
159 uint16_t fnum_src = 0;
160 uint16_t fnum_dst = 0;
161 struct security_descriptor *sd = NULL;
162 uint16_t attr;
163 time_t f_atime, f_ctime, f_mtime;
166 if (!copy_timestamps && !copy_acls && !copy_attrs)
167 return NT_STATUS_OK;
169 /* open file/dir on the originating server */
171 DEBUGADD(3,("opening %s %s on originating server\n",
172 is_file?"file":"dir", src_name));
174 if (!NT_STATUS_IS_OK(cli_ntcreate(cli_share_src, src_name, 0, READ_CONTROL_ACCESS, 0,
175 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0x0, 0x0, &fnum_src))) {
176 DEBUGADD(0,("cannot open %s %s on originating server %s\n",
177 is_file?"file":"dir", src_name, cli_errstr(cli_share_src)));
178 nt_status = cli_nt_error(cli_share_src);
179 goto out;
183 if (copy_acls) {
185 /* get the security descriptor */
186 sd = cli_query_secdesc(cli_share_src, fnum_src, mem_ctx);
187 if (!sd) {
188 DEBUG(0,("failed to get security descriptor: %s\n",
189 cli_errstr(cli_share_src)));
190 nt_status = cli_nt_error(cli_share_src);
191 goto out;
194 if (c->opt_verbose && DEBUGLEVEL >= 3)
195 display_sec_desc(sd);
199 if (copy_attrs || copy_timestamps) {
201 /* get file attributes */
202 if (!NT_STATUS_IS_OK(cli_getattrE(cli_share_src, fnum_src, &attr, NULL,
203 &f_ctime, &f_atime, &f_mtime))) {
204 DEBUG(0,("failed to get file-attrs: %s\n",
205 cli_errstr(cli_share_src)));
206 nt_status = cli_nt_error(cli_share_src);
207 goto out;
212 /* open the file/dir on the destination server */
214 if (!NT_STATUS_IS_OK(cli_ntcreate(cli_share_dst, dst_name, 0, WRITE_DAC_ACCESS | WRITE_OWNER_ACCESS, 0,
215 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0x0, 0x0, &fnum_dst))) {
216 DEBUG(0,("failed to open %s on the destination server: %s: %s\n",
217 is_file?"file":"dir", dst_name, cli_errstr(cli_share_dst)));
218 nt_status = cli_nt_error(cli_share_dst);
219 goto out;
222 if (copy_timestamps) {
224 /* set timestamps */
225 if (!NT_STATUS_IS_OK(cli_setattrE(cli_share_dst, fnum_dst, f_ctime, f_atime, f_mtime))) {
226 DEBUG(0,("failed to set file-attrs (timestamps): %s\n",
227 cli_errstr(cli_share_dst)));
228 nt_status = cli_nt_error(cli_share_dst);
229 goto out;
233 if (copy_acls) {
234 NTSTATUS status;
236 /* set acls */
237 status = cli_set_secdesc(cli_share_dst, fnum_dst, sd);
238 if (!NT_STATUS_IS_OK(status)) {
239 DEBUG(0, ("could not set secdesc on %s: %s\n",
240 dst_name, nt_errstr(status)));
241 nt_status = status;
242 goto out;
246 if (copy_attrs) {
248 /* set attrs */
249 if (!NT_STATUS_IS_OK(cli_setatr(cli_share_dst, dst_name, attr, 0))) {
250 DEBUG(0,("failed to set file-attrs: %s\n",
251 cli_errstr(cli_share_dst)));
252 nt_status = cli_nt_error(cli_share_dst);
253 goto out;
258 /* closing files */
260 if (!NT_STATUS_IS_OK(cli_close(cli_share_src, fnum_src))) {
261 d_fprintf(stderr,
262 _("could not close %s on originating server: %s\n"),
263 is_file?"file":"dir", cli_errstr(cli_share_src));
264 nt_status = cli_nt_error(cli_share_src);
265 goto out;
268 if (!NT_STATUS_IS_OK(cli_close(cli_share_dst, fnum_dst))) {
269 d_fprintf(stderr,
270 _("could not close %s on destination server: %s\n"),
271 is_file?"file":"dir", cli_errstr(cli_share_dst));
272 nt_status = cli_nt_error(cli_share_dst);
273 goto out;
277 nt_status = NT_STATUS_OK;
279 out:
281 /* cleaning up */
282 if (fnum_src)
283 cli_close(cli_share_src, fnum_src);
285 if (fnum_dst)
286 cli_close(cli_share_dst, fnum_dst);
288 return nt_status;
292 * Copy a file or directory from a connected share to another connected share
294 * @param c A net_context structure
295 * @param mem_ctx A talloc-context
296 * @param cli_share_src A connected cli_state
297 * @param cli_share_dst A connected cli_state
298 * @param src_file The source file-name
299 * @param dst_file The destination file-name
300 * @param copy_acls Whether to copy acls
301 * @param copy_attrs Whether to copy DOS attributes
302 * @param copy_timestamps Whether to preserve timestamps
303 * @param is_file Whether this file is a file or a dir
305 * @return Normal NTSTATUS return.
308 NTSTATUS net_copy_file(struct net_context *c,
309 TALLOC_CTX *mem_ctx,
310 struct cli_state *cli_share_src,
311 struct cli_state *cli_share_dst,
312 const char *src_name, const char *dst_name,
313 bool copy_acls, bool copy_attrs,
314 bool copy_timestamps, bool is_file)
316 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
317 uint16_t fnum_src = 0;
318 uint16_t fnum_dst = 0;
319 static int io_bufsize = 64512;
320 int read_size = io_bufsize;
321 char *data = NULL;
322 off_t nread = 0;
325 if (!src_name || !dst_name)
326 goto out;
328 if (cli_share_src == NULL || cli_share_dst == NULL)
329 goto out;
331 /* open on the originating server */
332 DEBUGADD(3,("opening %s %s on originating server\n",
333 is_file ? "file":"dir", src_name));
334 if (is_file)
335 nt_status = cli_open(cli_share_src, src_name, O_RDONLY, DENY_NONE, &fnum_src);
336 else
337 nt_status = cli_ntcreate(cli_share_src, src_name, 0, READ_CONTROL_ACCESS, 0,
338 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0x0, 0x0, &fnum_src);
340 if (!NT_STATUS_IS_OK(nt_status)) {
341 DEBUGADD(0,("cannot open %s %s on originating server %s\n",
342 is_file ? "file":"dir",
343 src_name, cli_errstr(cli_share_src)));
344 goto out;
348 if (is_file) {
350 /* open file on the destination server */
351 DEBUGADD(3,("opening file %s on destination server\n", dst_name));
352 nt_status = cli_open(cli_share_dst, dst_name,
353 O_RDWR|O_CREAT|O_TRUNC, DENY_NONE, &fnum_dst);
355 if (!NT_STATUS_IS_OK(nt_status)) {
356 DEBUGADD(1,("cannot create file %s on destination server: %s\n",
357 dst_name, cli_errstr(cli_share_dst)));
358 goto out;
361 /* allocate memory */
362 if (!(data = (char *)SMB_MALLOC(read_size))) {
363 d_fprintf(stderr, _("malloc fail for size %d\n"),
364 read_size);
365 nt_status = NT_STATUS_NO_MEMORY;
366 goto out;
372 if (c->opt_verbose) {
374 d_printf(_("copying [\\\\%s\\%s%s] => [\\\\%s\\%s%s] "
375 "%s ACLs and %s DOS Attributes %s\n"),
376 cli_share_src->desthost, cli_share_src->share, src_name,
377 cli_share_dst->desthost, cli_share_dst->share, dst_name,
378 copy_acls ? _("with") : _("without"),
379 copy_attrs ? _("with") : _("without"),
380 copy_timestamps ? _("(preserving timestamps)") : "" );
384 while (is_file) {
386 /* copying file */
387 int n, ret;
388 n = cli_read(cli_share_src, fnum_src, data, nread,
389 read_size);
391 if (n <= 0)
392 break;
394 ret = cli_write(cli_share_dst, fnum_dst, 0, data,
395 nread, n);
397 if (n != ret) {
398 d_fprintf(stderr, _("Error writing file: %s\n"),
399 cli_errstr(cli_share_dst));
400 nt_status = cli_nt_error(cli_share_dst);
401 goto out;
404 nread += n;
408 if (!is_file && !NT_STATUS_IS_OK(cli_chkpath(cli_share_dst, dst_name))) {
410 /* creating dir */
411 DEBUGADD(3,("creating dir %s on the destination server\n",
412 dst_name));
414 if (!NT_STATUS_IS_OK(cli_mkdir(cli_share_dst, dst_name))) {
415 DEBUG(0,("cannot create directory %s: %s\n",
416 dst_name, cli_errstr(cli_share_dst)));
417 nt_status = NT_STATUS_NO_SUCH_FILE;
420 if (!NT_STATUS_IS_OK(cli_chkpath(cli_share_dst, dst_name))) {
421 d_fprintf(stderr,
422 _("cannot check for directory %s: %s\n"),
423 dst_name, cli_errstr(cli_share_dst));
424 goto out;
429 /* closing files */
430 if (!NT_STATUS_IS_OK(cli_close(cli_share_src, fnum_src))) {
431 d_fprintf(stderr,
432 _("could not close file on originating server: %s\n"),
433 cli_errstr(cli_share_src));
434 nt_status = cli_nt_error(cli_share_src);
435 goto out;
438 if (is_file && !NT_STATUS_IS_OK(cli_close(cli_share_dst, fnum_dst))) {
439 d_fprintf(stderr,
440 _("could not close file on destination server: %s\n"),
441 cli_errstr(cli_share_dst));
442 nt_status = cli_nt_error(cli_share_dst);
443 goto out;
446 /* possibly we have to copy some file-attributes / acls / sd */
447 nt_status = net_copy_fileattr(c, mem_ctx, cli_share_src, cli_share_dst,
448 src_name, dst_name, copy_acls,
449 copy_attrs, copy_timestamps, is_file);
450 if (!NT_STATUS_IS_OK(nt_status))
451 goto out;
454 nt_status = NT_STATUS_OK;
456 out:
458 /* cleaning up */
459 if (fnum_src)
460 cli_close(cli_share_src, fnum_src);
462 if (fnum_dst)
463 cli_close(cli_share_dst, fnum_dst);
465 SAFE_FREE(data);
467 return nt_status;
471 * Copy a driverfile from on connected share to another connected share
472 * This silently assumes that a driver-file is picked up from
474 * \\src_server\print$\{arch}\{version}\file
476 * and copied to
478 * \\dst_server\print$\{arch}\file
480 * to be added via setdriver-calls later.
481 * @param c A net_context structure
482 * @param mem_ctx A talloc-context
483 * @param cli_share_src A cli_state connected to source print$-share
484 * @param cli_share_dst A cli_state connected to destination print$-share
485 * @param file The file-name to be copied
486 * @param short_archi The name of the driver-architecture (short form)
488 * @return Normal NTSTATUS return.
491 static NTSTATUS net_copy_driverfile(struct net_context *c,
492 TALLOC_CTX *mem_ctx,
493 struct cli_state *cli_share_src,
494 struct cli_state *cli_share_dst,
495 const char *file, const char *short_archi) {
497 const char *p;
498 char *src_name;
499 char *dst_name;
500 char *version = NULL;
501 char *filename = NULL;
502 char *tok;
504 if (!file) {
505 return NT_STATUS_OK;
508 /* scroll through the file until we have the part
509 beyond archi_table.short_archi */
510 p = file;
511 while (next_token_talloc(mem_ctx, &p, &tok, "\\")) {
512 if (strequal(tok, short_archi)) {
513 next_token_talloc(mem_ctx, &p, &version, "\\");
514 next_token_talloc(mem_ctx, &p, &filename, "\\");
518 if (version == NULL || filename == NULL) {
519 return NT_STATUS_UNSUCCESSFUL;
522 /* build source file name */
523 src_name = talloc_asprintf(mem_ctx, "\\%s\\%s\\%s",
524 short_archi, version, filename);
525 if (src_name == NULL) {
526 return NT_STATUS_NO_MEMORY;
529 /* create destination file name */
530 dst_name = talloc_asprintf(mem_ctx, "\\%s\\%s", short_archi, filename);
531 if (dst_name == NULL) {
532 return NT_STATUS_NO_MEMORY;
536 /* finally copy the file */
537 return net_copy_file(c, mem_ctx, cli_share_src, cli_share_dst,
538 src_name, dst_name, false, false, false, true);
542 * Check for existing Architecture directory on a given server
544 * @param cli_share A cli_state connected to a print$-share
545 * @param short_archi The Architecture for the print-driver
547 * @return Normal NTSTATUS return.
550 static NTSTATUS check_arch_dir(struct cli_state *cli_share, const char *short_archi)
553 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
554 char *dir;
556 if (asprintf(&dir, "\\%s", short_archi) < 0) {
557 return NT_STATUS_NO_MEMORY;
560 DEBUG(10,("creating print-driver dir for architecture: %s\n",
561 short_archi));
563 if (!NT_STATUS_IS_OK(cli_mkdir(cli_share, dir))) {
564 DEBUG(1,("cannot create directory %s: %s\n",
565 dir, cli_errstr(cli_share)));
566 nt_status = NT_STATUS_NO_SUCH_FILE;
569 if (!NT_STATUS_IS_OK(cli_chkpath(cli_share, dir))) {
570 d_fprintf(stderr, _("cannot check %s: %s\n"),
571 dir, cli_errstr(cli_share));
572 goto out;
575 nt_status = NT_STATUS_OK;
577 out:
578 SAFE_FREE(dir);
579 return nt_status;
583 * Copy a print-driver (level 3) from one connected print$-share to another
584 * connected print$-share
586 * @param c A net_context structure
587 * @param mem_ctx A talloc-context
588 * @param cli_share_src A cli_state connected to a print$-share
589 * @param cli_share_dst A cli_state connected to a print$-share
590 * @param short_archi The Architecture for the print-driver
591 * @param i1 The DRIVER_INFO_3-struct
593 * @return Normal NTSTATUS return.
596 static NTSTATUS copy_print_driver_3(struct net_context *c,
597 TALLOC_CTX *mem_ctx,
598 struct cli_state *cli_share_src,
599 struct cli_state *cli_share_dst,
600 const char *short_archi,
601 struct spoolss_DriverInfo3 *r)
603 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
604 int i;
606 if (r == NULL) {
607 return nt_status;
610 if (c->opt_verbose)
611 d_printf(_("copying driver: [%s], for architecture: [%s], "
612 "version: [%d]\n"),
613 r->driver_name, short_archi, r->version);
615 nt_status = net_copy_driverfile(c, mem_ctx, cli_share_src, cli_share_dst,
616 r->driver_path, short_archi);
617 if (!NT_STATUS_IS_OK(nt_status))
618 return nt_status;
620 nt_status = net_copy_driverfile(c, mem_ctx, cli_share_src, cli_share_dst,
621 r->data_file, short_archi);
622 if (!NT_STATUS_IS_OK(nt_status))
623 return nt_status;
625 nt_status = net_copy_driverfile(c, mem_ctx, cli_share_src, cli_share_dst,
626 r->config_file, short_archi);
627 if (!NT_STATUS_IS_OK(nt_status))
628 return nt_status;
630 nt_status = net_copy_driverfile(c, mem_ctx, cli_share_src, cli_share_dst,
631 r->help_file, short_archi);
632 if (!NT_STATUS_IS_OK(nt_status))
633 return nt_status;
635 for (i=0; r->dependent_files[i] != NULL; i++) {
637 nt_status = net_copy_driverfile(c, mem_ctx,
638 cli_share_src, cli_share_dst,
639 r->dependent_files[i], short_archi);
640 if (!NT_STATUS_IS_OK(nt_status)) {
641 return nt_status;
645 return NT_STATUS_OK;
649 * net_spoolss-functions
650 * =====================
652 * the net_spoolss-functions aim to simplify spoolss-client-functions
653 * required during the migration-process wrt buffer-sizes, returned
654 * error-codes, etc.
656 * this greatly reduces the complexitiy of the migrate-functions.
660 static bool net_spoolss_enum_printers(struct rpc_pipe_client *pipe_hnd,
661 TALLOC_CTX *mem_ctx,
662 char *name,
663 uint32_t flags,
664 uint32_t level,
665 uint32_t *num_printers,
666 union spoolss_PrinterInfo **info)
668 WERROR result;
670 /* enum printers */
672 result = rpccli_spoolss_enumprinters(pipe_hnd, mem_ctx,
673 flags,
674 name,
675 level,
677 num_printers,
678 info);
679 if (!W_ERROR_IS_OK(result)) {
680 printf(_("cannot enum printers: %s\n"), win_errstr(result));
681 return false;
684 return true;
687 static bool net_spoolss_open_printer_ex(struct rpc_pipe_client *pipe_hnd,
688 TALLOC_CTX *mem_ctx,
689 const char *printername,
690 uint32_t access_required,
691 const char *username,
692 struct policy_handle *hnd)
694 WERROR result;
695 fstring printername2;
697 fstrcpy(printername2, pipe_hnd->srv_name_slash);
698 fstrcat(printername2, "\\");
699 fstrcat(printername2, printername);
701 DEBUG(10,("connecting to: %s as %s for %s and access: %x\n",
702 pipe_hnd->srv_name_slash, username, printername2, access_required));
704 /* open printer */
705 result = rpccli_spoolss_openprinter_ex(pipe_hnd, mem_ctx,
706 printername2,
707 access_required,
708 hnd);
710 /* be more verbose */
711 if (W_ERROR_V(result) == W_ERROR_V(WERR_ACCESS_DENIED)) {
712 d_fprintf(stderr,
713 _("no access to printer [%s] on [%s] for user [%s] "
714 "granted\n"),
715 printername2, pipe_hnd->srv_name_slash, username);
716 return false;
719 if (!W_ERROR_IS_OK(result)) {
720 d_fprintf(stderr,_("cannot open printer %s on server %s: %s\n"),
721 printername2, pipe_hnd->srv_name_slash, win_errstr(result));
722 return false;
725 DEBUG(2,("got printer handle for printer: %s, server: %s\n",
726 printername2, pipe_hnd->srv_name_slash));
728 return true;
731 static bool net_spoolss_getprinter(struct rpc_pipe_client *pipe_hnd,
732 TALLOC_CTX *mem_ctx,
733 struct policy_handle *hnd,
734 uint32_t level,
735 union spoolss_PrinterInfo *info)
737 WERROR result;
739 /* getprinter call */
740 result = rpccli_spoolss_getprinter(pipe_hnd, mem_ctx,
741 hnd,
742 level,
743 0, /* offered */
744 info);
745 if (!W_ERROR_IS_OK(result)) {
746 printf(_("cannot get printer-info: %s\n"), win_errstr(result));
747 return false;
750 return true;
753 static bool net_spoolss_setprinter(struct rpc_pipe_client *pipe_hnd,
754 TALLOC_CTX *mem_ctx,
755 struct policy_handle *hnd,
756 uint32_t level,
757 union spoolss_PrinterInfo *info)
759 WERROR result;
760 NTSTATUS status;
761 struct spoolss_SetPrinterInfoCtr info_ctr;
762 struct spoolss_SetPrinterInfo2 info2;
763 struct spoolss_DevmodeContainer devmode_ctr;
764 struct sec_desc_buf secdesc_ctr;
766 ZERO_STRUCT(devmode_ctr);
767 ZERO_STRUCT(secdesc_ctr);
769 /* setprinter call */
771 info_ctr.level = level;
772 switch (level) {
773 case 0:
774 info_ctr.info.info0 = (struct spoolss_SetPrinterInfo0 *)
775 (void *)&info->info0;
776 break;
777 case 1:
778 info_ctr.info.info1 = (struct spoolss_SetPrinterInfo1 *)
779 (void *)&info->info1;
780 break;
781 case 2:
782 spoolss_printerinfo2_to_setprinterinfo2(&info->info2, &info2);
783 info_ctr.info.info2 = &info2;
784 break;
785 case 3:
786 info_ctr.info.info3 = (struct spoolss_SetPrinterInfo3 *)
787 (void *)&info->info3;
788 break;
789 case 4:
790 info_ctr.info.info4 = (struct spoolss_SetPrinterInfo4 *)
791 (void *)&info->info4;
792 break;
793 case 5:
794 info_ctr.info.info5 = (struct spoolss_SetPrinterInfo5 *)
795 (void *)&info->info5;
796 break;
797 case 6:
798 info_ctr.info.info6 = (struct spoolss_SetPrinterInfo6 *)
799 (void *)&info->info6;
800 break;
801 case 7:
802 info_ctr.info.info7 = (struct spoolss_SetPrinterInfo7 *)
803 (void *)&info->info7;
804 break;
805 #if 0 /* FIXME GD */
806 case 8:
807 info_ctr.info.info8 = (struct spoolss_SetPrinterInfo8 *)
808 (void *)&info->info8;
809 break;
810 case 9:
811 info_ctr.info.info9 = (struct spoolss_SetPrinterInfo9 *)
812 (void *)&info->info9;
813 break;
814 #endif
815 default:
816 break; /* FIXME */
819 status = rpccli_spoolss_SetPrinter(pipe_hnd, mem_ctx,
820 hnd,
821 &info_ctr,
822 &devmode_ctr,
823 &secdesc_ctr,
824 0, /* command */
825 &result);
827 if (!W_ERROR_IS_OK(result)) {
828 printf(_("cannot set printer-info: %s\n"), win_errstr(result));
829 return false;
832 return true;
836 static bool net_spoolss_setprinterdata(struct rpc_pipe_client *pipe_hnd,
837 TALLOC_CTX *mem_ctx,
838 struct policy_handle *hnd,
839 const char *value_name,
840 enum winreg_Type type,
841 uint8_t *data,
842 uint32_t offered)
844 WERROR result;
845 NTSTATUS status;
847 /* setprinterdata call */
848 status = rpccli_spoolss_SetPrinterData(pipe_hnd, mem_ctx,
849 hnd,
850 value_name,
851 type,
852 data,
853 offered,
854 &result);
856 if (!W_ERROR_IS_OK(result)) {
857 printf (_("unable to set printerdata: %s\n"),
858 win_errstr(result));
859 return false;
862 return true;
866 static bool net_spoolss_enumprinterkey(struct rpc_pipe_client *pipe_hnd,
867 TALLOC_CTX *mem_ctx,
868 struct policy_handle *hnd,
869 const char *keyname,
870 const char ***keylist)
872 WERROR result;
874 /* enumprinterkey call */
875 result = rpccli_spoolss_enumprinterkey(pipe_hnd, mem_ctx, hnd, keyname, keylist, 0);
877 if (!W_ERROR_IS_OK(result)) {
878 printf(_("enumprinterkey failed: %s\n"), win_errstr(result));
879 return false;
882 return true;
885 static bool net_spoolss_enumprinterdataex(struct rpc_pipe_client *pipe_hnd,
886 TALLOC_CTX *mem_ctx,
887 uint32_t offered,
888 struct policy_handle *hnd,
889 const char *keyname,
890 uint32_t *count,
891 struct spoolss_PrinterEnumValues **info)
893 WERROR result;
895 /* enumprinterdataex call */
896 result = rpccli_spoolss_enumprinterdataex(pipe_hnd, mem_ctx,
897 hnd,
898 keyname,
899 0, /* offered */
900 count,
901 info);
903 if (!W_ERROR_IS_OK(result)) {
904 printf(_("enumprinterdataex failed: %s\n"), win_errstr(result));
905 return false;
908 return true;
912 static bool net_spoolss_setprinterdataex(struct rpc_pipe_client *pipe_hnd,
913 TALLOC_CTX *mem_ctx,
914 struct policy_handle *hnd,
915 const char *keyname,
916 struct regval_blob *value)
918 WERROR result;
919 NTSTATUS status;
921 /* setprinterdataex call */
922 status = rpccli_spoolss_SetPrinterDataEx(pipe_hnd, mem_ctx,
923 hnd,
924 keyname,
925 regval_name(value),
926 regval_type(value),
927 regval_data_p(value),
928 regval_size(value),
929 &result);
931 if (!W_ERROR_IS_OK(result)) {
932 printf(_("could not set printerdataex: %s\n"),
933 win_errstr(result));
934 return false;
937 return true;
940 static bool net_spoolss_enumforms(struct rpc_pipe_client *pipe_hnd,
941 TALLOC_CTX *mem_ctx,
942 struct policy_handle *hnd,
943 int level,
944 uint32_t *num_forms,
945 union spoolss_FormInfo **forms)
947 WERROR result;
949 /* enumforms call */
950 result = rpccli_spoolss_enumforms(pipe_hnd, mem_ctx,
951 hnd,
952 level,
954 num_forms,
955 forms);
956 if (!W_ERROR_IS_OK(result)) {
957 printf(_("could not enum forms: %s\n"), win_errstr(result));
958 return false;
961 return true;
964 static bool net_spoolss_enumprinterdrivers (struct rpc_pipe_client *pipe_hnd,
965 TALLOC_CTX *mem_ctx,
966 uint32_t level, const char *env,
967 uint32_t *count,
968 union spoolss_DriverInfo **info)
970 WERROR result;
972 /* enumprinterdrivers call */
973 result = rpccli_spoolss_enumprinterdrivers(pipe_hnd, mem_ctx,
974 pipe_hnd->srv_name_slash,
975 env,
976 level,
978 count,
979 info);
980 if (!W_ERROR_IS_OK(result)) {
981 if (W_ERROR_V(result) != W_ERROR_V(WERR_INVALID_ENVIRONMENT)) {
982 printf(_("cannot enum drivers for environment %s: %s\n"), env,
983 win_errstr(result));
984 return false;
985 } else {
986 printf(_("Server does not support environment [%s]\n"),
987 env);
991 return true;
994 static bool net_spoolss_getprinterdriver(struct rpc_pipe_client *pipe_hnd,
995 TALLOC_CTX *mem_ctx,
996 struct policy_handle *hnd, uint32_t level,
997 const char *env, int version,
998 union spoolss_DriverInfo *info)
1000 WERROR result;
1001 uint32_t server_major_version;
1002 uint32_t server_minor_version;
1004 /* getprinterdriver call */
1005 result = rpccli_spoolss_getprinterdriver2(pipe_hnd, mem_ctx,
1006 hnd,
1007 env,
1008 level,
1010 version,
1012 info,
1013 &server_major_version,
1014 &server_minor_version);
1015 if (!W_ERROR_IS_OK(result)) {
1016 DEBUG(1,("cannot get driver (for architecture: %s): %s\n",
1017 env, win_errstr(result)));
1018 if (W_ERROR_V(result) != W_ERROR_V(WERR_UNKNOWN_PRINTER_DRIVER) &&
1019 W_ERROR_V(result) != W_ERROR_V(WERR_INVALID_ENVIRONMENT)) {
1020 printf(_("cannot get driver: %s\n"),
1021 win_errstr(result));
1023 return false;
1026 return true;
1030 static bool net_spoolss_addprinterdriver(struct rpc_pipe_client *pipe_hnd,
1031 TALLOC_CTX *mem_ctx, uint32_t level,
1032 union spoolss_DriverInfo *info)
1034 WERROR result;
1035 NTSTATUS status;
1036 struct spoolss_AddDriverInfoCtr info_ctr;
1038 info_ctr.level = level;
1040 switch (level) {
1041 case 2:
1042 info_ctr.info.info2 = (struct spoolss_AddDriverInfo2 *)
1043 (void *)&info->info2;
1044 break;
1045 case 3:
1046 info_ctr.info.info3 = (struct spoolss_AddDriverInfo3 *)
1047 (void *)&info->info3;
1048 break;
1049 default:
1050 printf(_("unsupported info level: %d\n"), level);
1051 return false;
1054 /* addprinterdriver call */
1055 status = rpccli_spoolss_AddPrinterDriver(pipe_hnd, mem_ctx,
1056 pipe_hnd->srv_name_slash,
1057 &info_ctr,
1058 &result);
1059 /* be more verbose */
1060 if (W_ERROR_V(result) == W_ERROR_V(WERR_ACCESS_DENIED)) {
1061 printf(_("You are not allowed to add drivers\n"));
1062 return false;
1064 if (!W_ERROR_IS_OK(result)) {
1065 printf(_("cannot add driver: %s\n"), win_errstr(result));
1066 return false;
1069 return true;
1073 * abstraction function to get uint32_t num_printers and PRINTER_INFO_CTR ctr
1074 * for a single printer or for all printers depending on argc/argv
1077 static bool get_printer_info(struct rpc_pipe_client *pipe_hnd,
1078 TALLOC_CTX *mem_ctx,
1079 int level,
1080 int argc,
1081 const char **argv,
1082 uint32_t *num_printers,
1083 union spoolss_PrinterInfo **info_p)
1085 struct policy_handle hnd;
1087 /* no arguments given, enumerate all printers */
1088 if (argc == 0) {
1090 if (!net_spoolss_enum_printers(pipe_hnd, mem_ctx, NULL,
1091 PRINTER_ENUM_LOCAL|PRINTER_ENUM_SHARED,
1092 level, num_printers, info_p))
1093 return false;
1095 goto out;
1098 /* argument given, get a single printer by name */
1099 if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, argv[0],
1100 MAXIMUM_ALLOWED_ACCESS,
1101 pipe_hnd->auth->user_name,
1102 &hnd))
1103 return false;
1105 *info_p = talloc_zero(mem_ctx, union spoolss_PrinterInfo);
1106 if (*info_p == NULL) {
1107 return false;
1110 if (!net_spoolss_getprinter(pipe_hnd, mem_ctx, &hnd, level, *info_p)) {
1111 rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd, NULL);
1112 return false;
1115 rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd, NULL);
1117 *num_printers = 1;
1119 out:
1120 DEBUG(3,("got %d printers\n", *num_printers));
1122 return true;
1127 * List print-queues (including local printers that are not shared)
1129 * All parameters are provided by the run_rpc_command function, except for
1130 * argc, argv which are passed through.
1132 * @param c A net_context structure
1133 * @param domain_sid The domain sid aquired from the remote server
1134 * @param cli A cli_state connected to the server.
1135 * @param mem_ctx Talloc context, destoyed on compleation of the function.
1136 * @param argc Standard main() style argc
1137 * @param argv Standard main() style argv. Initial components are already
1138 * stripped
1140 * @return Normal NTSTATUS return.
1143 NTSTATUS rpc_printer_list_internals(struct net_context *c,
1144 const struct dom_sid *domain_sid,
1145 const char *domain_name,
1146 struct cli_state *cli,
1147 struct rpc_pipe_client *pipe_hnd,
1148 TALLOC_CTX *mem_ctx,
1149 int argc,
1150 const char **argv)
1152 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1153 uint32_t i, num_printers;
1154 uint32_t level = 2;
1155 const char *printername, *sharename;
1156 union spoolss_PrinterInfo *info;
1158 printf("listing printers\n");
1160 if (!get_printer_info(pipe_hnd, mem_ctx, level, argc, argv, &num_printers, &info))
1161 return nt_status;
1163 for (i = 0; i < num_printers; i++) {
1165 /* do some initialization */
1166 printername = info[i].info2.printername;
1167 sharename = info[i].info2.sharename;
1169 if (printername && sharename) {
1170 d_printf(_("printer %d: %s, shared as: %s\n"),
1171 i+1, printername, sharename);
1175 return NT_STATUS_OK;
1179 * List printer-drivers from a server
1181 * All parameters are provided by the run_rpc_command function, except for
1182 * argc, argv which are passed through.
1184 * @param c A net_context structure
1185 * @param domain_sid The domain sid aquired from the remote server
1186 * @param cli A cli_state connected to the server.
1187 * @param mem_ctx Talloc context, destoyed on compleation of the function.
1188 * @param argc Standard main() style argc
1189 * @param argv Standard main() style argv. Initial components are already
1190 * stripped
1192 * @return Normal NTSTATUS return.
1195 NTSTATUS rpc_printer_driver_list_internals(struct net_context *c,
1196 const struct dom_sid *domain_sid,
1197 const char *domain_name,
1198 struct cli_state *cli,
1199 struct rpc_pipe_client *pipe_hnd,
1200 TALLOC_CTX *mem_ctx,
1201 int argc,
1202 const char **argv)
1204 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1205 uint32_t i;
1206 uint32_t level = 3;
1207 union spoolss_DriverInfo *info;
1208 int d;
1210 printf(_("listing printer-drivers\n"));
1212 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1214 uint32_t num_drivers;
1216 /* enum remote drivers */
1217 if (!net_spoolss_enumprinterdrivers(pipe_hnd, mem_ctx, level,
1218 archi_table[i].long_archi,
1219 &num_drivers, &info)) {
1220 nt_status = NT_STATUS_UNSUCCESSFUL;
1221 goto done;
1224 if (num_drivers == 0) {
1225 d_printf(_("no drivers found on server for "
1226 "architecture: [%s].\n"),
1227 archi_table[i].long_archi);
1228 continue;
1231 d_printf(_("got %d printer-drivers for architecture: [%s]\n"),
1232 num_drivers, archi_table[i].long_archi);
1235 /* do something for all drivers for architecture */
1236 for (d = 0; d < num_drivers; d++) {
1237 display_print_driver3(&info[d].info3);
1241 nt_status = NT_STATUS_OK;
1243 done:
1244 return nt_status;
1249 * Publish print-queues with args-wrapper
1251 * @param cli A cli_state connected to the server.
1252 * @param mem_ctx Talloc context, destoyed on compleation of the function.
1253 * @param argc Standard main() style argc
1254 * @param argv Standard main() style argv. Initial components are already
1255 * stripped
1256 * @param action
1258 * @return Normal NTSTATUS return.
1261 static NTSTATUS rpc_printer_publish_internals_args(struct rpc_pipe_client *pipe_hnd,
1262 TALLOC_CTX *mem_ctx,
1263 int argc,
1264 const char **argv,
1265 uint32_t action)
1267 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1268 uint32_t i, num_printers;
1269 uint32_t level = 7;
1270 const char *printername, *sharename;
1271 union spoolss_PrinterInfo *info_enum;
1272 union spoolss_PrinterInfo info;
1273 struct spoolss_SetPrinterInfoCtr info_ctr;
1274 struct spoolss_DevmodeContainer devmode_ctr;
1275 struct sec_desc_buf secdesc_ctr;
1276 struct policy_handle hnd;
1277 WERROR result;
1278 const char *action_str;
1280 if (!get_printer_info(pipe_hnd, mem_ctx, 2, argc, argv, &num_printers, &info_enum))
1281 return nt_status;
1283 for (i = 0; i < num_printers; i++) {
1285 /* do some initialization */
1286 printername = info_enum[i].info2.printername;
1287 sharename = info_enum[i].info2.sharename;
1288 if (!printername || !sharename) {
1289 goto done;
1292 /* open printer handle */
1293 if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, sharename,
1294 PRINTER_ALL_ACCESS, pipe_hnd->auth->user_name, &hnd))
1295 goto done;
1297 /* check for existing dst printer */
1298 if (!net_spoolss_getprinter(pipe_hnd, mem_ctx, &hnd, level, &info))
1299 goto done;
1301 /* check action and set string */
1302 switch (action) {
1303 case DSPRINT_PUBLISH:
1304 action_str = N_("published");
1305 break;
1306 case DSPRINT_UPDATE:
1307 action_str = N_("updated");
1308 break;
1309 case DSPRINT_UNPUBLISH:
1310 action_str = N_("unpublished");
1311 break;
1312 default:
1313 action_str = N_("unknown action");
1314 printf(_("unkown action: %d\n"), action);
1315 break;
1318 info.info7.action = action;
1319 info_ctr.level = 7;
1320 info_ctr.info.info7 = (struct spoolss_SetPrinterInfo7 *)
1321 (void *)&info.info7;
1323 ZERO_STRUCT(devmode_ctr);
1324 ZERO_STRUCT(secdesc_ctr);
1326 nt_status = rpccli_spoolss_SetPrinter(pipe_hnd, mem_ctx,
1327 &hnd,
1328 &info_ctr,
1329 &devmode_ctr,
1330 &secdesc_ctr,
1331 0, /* command */
1332 &result);
1334 if (!W_ERROR_IS_OK(result) && !W_ERROR_EQUAL(result, WERR_IO_PENDING)) {
1335 if ((action == DSPRINT_UPDATE) && W_ERROR_EQUAL(result, W_ERROR(0x80070002))) {
1336 printf(_("printer not published yet\n"));
1337 } else {
1338 printf(_("cannot set printer-info: %s\n"),
1339 win_errstr(result));
1341 goto done;
1344 printf(_("successfully %s printer %s in Active Directory\n"),
1345 action_str, sharename);
1348 nt_status = NT_STATUS_OK;
1350 done:
1351 if (is_valid_policy_hnd(&hnd))
1352 rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd, NULL);
1354 return nt_status;
1357 NTSTATUS rpc_printer_publish_publish_internals(struct net_context *c,
1358 const struct dom_sid *domain_sid,
1359 const char *domain_name,
1360 struct cli_state *cli,
1361 struct rpc_pipe_client *pipe_hnd,
1362 TALLOC_CTX *mem_ctx,
1363 int argc,
1364 const char **argv)
1366 return rpc_printer_publish_internals_args(pipe_hnd, mem_ctx, argc, argv, DSPRINT_PUBLISH);
1369 NTSTATUS rpc_printer_publish_unpublish_internals(struct net_context *c,
1370 const struct dom_sid *domain_sid,
1371 const char *domain_name,
1372 struct cli_state *cli,
1373 struct rpc_pipe_client *pipe_hnd,
1374 TALLOC_CTX *mem_ctx,
1375 int argc,
1376 const char **argv)
1378 return rpc_printer_publish_internals_args(pipe_hnd, mem_ctx, argc, argv, DSPRINT_UNPUBLISH);
1381 NTSTATUS rpc_printer_publish_update_internals(struct net_context *c,
1382 const struct dom_sid *domain_sid,
1383 const char *domain_name,
1384 struct cli_state *cli,
1385 struct rpc_pipe_client *pipe_hnd,
1386 TALLOC_CTX *mem_ctx,
1387 int argc,
1388 const char **argv)
1390 return rpc_printer_publish_internals_args(pipe_hnd, mem_ctx, argc, argv, DSPRINT_UPDATE);
1394 * List print-queues w.r.t. their publishing state
1396 * All parameters are provided by the run_rpc_command function, except for
1397 * argc, argv which are passed through.
1399 * @param c A net_context structure
1400 * @param domain_sid The domain sid aquired from the remote server
1401 * @param cli A cli_state connected to the server.
1402 * @param mem_ctx Talloc context, destoyed on compleation of the function.
1403 * @param argc Standard main() style argc
1404 * @param argv Standard main() style argv. Initial components are already
1405 * stripped
1407 * @return Normal NTSTATUS return.
1410 NTSTATUS rpc_printer_publish_list_internals(struct net_context *c,
1411 const struct dom_sid *domain_sid,
1412 const char *domain_name,
1413 struct cli_state *cli,
1414 struct rpc_pipe_client *pipe_hnd,
1415 TALLOC_CTX *mem_ctx,
1416 int argc,
1417 const char **argv)
1419 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1420 uint32_t i, num_printers;
1421 uint32_t level = 7;
1422 const char *printername, *sharename;
1423 union spoolss_PrinterInfo *info_enum;
1424 union spoolss_PrinterInfo info;
1425 struct policy_handle hnd;
1426 int state;
1428 if (!get_printer_info(pipe_hnd, mem_ctx, 2, argc, argv, &num_printers, &info_enum))
1429 return nt_status;
1431 for (i = 0; i < num_printers; i++) {
1433 /* do some initialization */
1434 printername = info_enum[i].info2.printername;
1435 sharename = info_enum[i].info2.sharename;
1437 if (!printername || !sharename) {
1438 goto done;
1441 /* open printer handle */
1442 if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, sharename,
1443 PRINTER_ALL_ACCESS, cli->user_name, &hnd))
1444 goto done;
1446 /* check for existing dst printer */
1447 if (!net_spoolss_getprinter(pipe_hnd, mem_ctx, &hnd, level, &info))
1448 goto done;
1450 if (!info.info7.guid) {
1451 goto done;
1453 state = info.info7.action;
1454 switch (state) {
1455 case DSPRINT_PUBLISH:
1456 printf(_("printer [%s] is published"),
1457 sharename);
1458 if (c->opt_verbose)
1459 printf(_(", guid: %s"),info.info7.guid);
1460 printf("\n");
1461 break;
1462 case DSPRINT_UNPUBLISH:
1463 printf(_("printer [%s] is unpublished\n"),
1464 sharename);
1465 break;
1466 case DSPRINT_UPDATE:
1467 printf(_("printer [%s] is currently updating\n"),
1468 sharename);
1469 break;
1470 default:
1471 printf(_("unkown state: %d\n"), state);
1472 break;
1476 nt_status = NT_STATUS_OK;
1478 done:
1479 if (is_valid_policy_hnd(&hnd))
1480 rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd, NULL);
1482 return nt_status;
1486 * Migrate Printer-ACLs from a source server to the destination server
1488 * All parameters are provided by the run_rpc_command function, except for
1489 * argc, argv which are passed through.
1491 * @param c A net_context structure
1492 * @param domain_sid The domain sid aquired from the remote server
1493 * @param cli A cli_state connected to the server.
1494 * @param mem_ctx Talloc context, destoyed on compleation of the function.
1495 * @param argc Standard main() style argc
1496 * @param argv Standard main() style argv. Initial components are already
1497 * stripped
1499 * @return Normal NTSTATUS return.
1502 NTSTATUS rpc_printer_migrate_security_internals(struct net_context *c,
1503 const struct dom_sid *domain_sid,
1504 const char *domain_name,
1505 struct cli_state *cli,
1506 struct rpc_pipe_client *pipe_hnd,
1507 TALLOC_CTX *mem_ctx,
1508 int argc,
1509 const char **argv)
1511 /* TODO: what now, info2 or info3 ?
1512 convince jerry that we should add clientside setacls level 3 at least
1514 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1515 uint32_t i = 0;
1516 uint32_t num_printers;
1517 uint32_t level = 2;
1518 const char *printername, *sharename;
1519 struct rpc_pipe_client *pipe_hnd_dst = NULL;
1520 struct policy_handle hnd_src, hnd_dst;
1521 union spoolss_PrinterInfo *info_enum;
1522 struct cli_state *cli_dst = NULL;
1523 union spoolss_PrinterInfo info_src, info_dst;
1525 DEBUG(3,("copying printer ACLs\n"));
1527 /* connect destination PI_SPOOLSS */
1528 nt_status = connect_dst_pipe(c, &cli_dst, &pipe_hnd_dst,
1529 &ndr_table_spoolss.syntax_id);
1530 if (!NT_STATUS_IS_OK(nt_status))
1531 return nt_status;
1534 /* enum source printers */
1535 if (!get_printer_info(pipe_hnd, mem_ctx, level, argc, argv, &num_printers, &info_enum)) {
1536 nt_status = NT_STATUS_UNSUCCESSFUL;
1537 goto done;
1540 if (!num_printers) {
1541 printf (_("no printers found on server.\n"));
1542 nt_status = NT_STATUS_OK;
1543 goto done;
1546 /* do something for all printers */
1547 for (i = 0; i < num_printers; i++) {
1549 /* do some initialization */
1550 printername = info_enum[i].info2.printername;
1551 sharename = info_enum[i].info2.sharename;
1553 if (!printername || !sharename) {
1554 nt_status = NT_STATUS_UNSUCCESSFUL;
1555 goto done;
1558 /* we can reset NT_STATUS here because we do not
1559 get any real NT_STATUS-codes anymore from now on */
1560 nt_status = NT_STATUS_UNSUCCESSFUL;
1562 d_printf(_("migrating printer ACLs for: [%s] / [%s]\n"),
1563 printername, sharename);
1565 /* according to msdn you have specify these access-rights
1566 to see the security descriptor
1567 - READ_CONTROL (DACL)
1568 - ACCESS_SYSTEM_SECURITY (SACL)
1571 /* open src printer handle */
1572 if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, sharename,
1573 MAXIMUM_ALLOWED_ACCESS, cli->user_name, &hnd_src))
1574 goto done;
1576 /* open dst printer handle */
1577 if (!net_spoolss_open_printer_ex(pipe_hnd_dst, mem_ctx, sharename,
1578 PRINTER_ALL_ACCESS, cli_dst->user_name, &hnd_dst))
1579 goto done;
1581 /* check for existing dst printer */
1582 if (!net_spoolss_getprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, level, &info_dst))
1583 goto done;
1585 /* check for existing src printer */
1586 if (!net_spoolss_getprinter(pipe_hnd, mem_ctx, &hnd_src, 3, &info_src))
1587 goto done;
1589 /* Copy Security Descriptor */
1591 /* copy secdesc (info level 2) */
1592 info_dst.info2.devmode = NULL;
1593 info_dst.info2.secdesc = dup_sec_desc(mem_ctx, info_src.info3.secdesc);
1595 if (c->opt_verbose)
1596 display_sec_desc(info_dst.info2.secdesc);
1598 if (!net_spoolss_setprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, 2, &info_dst))
1599 goto done;
1601 DEBUGADD(1,("\tSetPrinter of SECDESC succeeded\n"));
1604 /* close printer handles here */
1605 if (is_valid_policy_hnd(&hnd_src)) {
1606 rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd_src, NULL);
1609 if (is_valid_policy_hnd(&hnd_dst)) {
1610 rpccli_spoolss_ClosePrinter(pipe_hnd_dst, mem_ctx, &hnd_dst, NULL);
1615 nt_status = NT_STATUS_OK;
1617 done:
1619 if (is_valid_policy_hnd(&hnd_src)) {
1620 rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd_src, NULL);
1623 if (is_valid_policy_hnd(&hnd_dst)) {
1624 rpccli_spoolss_ClosePrinter(pipe_hnd_dst, mem_ctx, &hnd_dst, NULL);
1627 if (cli_dst) {
1628 cli_shutdown(cli_dst);
1630 return nt_status;
1634 * Migrate printer-forms from a src server to the dst server
1636 * All parameters are provided by the run_rpc_command function, except for
1637 * argc, argv which are passed through.
1639 * @param c A net_context structure
1640 * @param domain_sid The domain sid aquired from the remote server
1641 * @param cli A cli_state connected to the server.
1642 * @param mem_ctx Talloc context, destoyed on compleation of the function.
1643 * @param argc Standard main() style argc
1644 * @param argv Standard main() style argv. Initial components are already
1645 * stripped
1647 * @return Normal NTSTATUS return.
1650 NTSTATUS rpc_printer_migrate_forms_internals(struct net_context *c,
1651 const struct dom_sid *domain_sid,
1652 const char *domain_name,
1653 struct cli_state *cli,
1654 struct rpc_pipe_client *pipe_hnd,
1655 TALLOC_CTX *mem_ctx,
1656 int argc,
1657 const char **argv)
1659 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1660 WERROR result;
1661 uint32_t i, f;
1662 uint32_t num_printers;
1663 uint32_t level = 1;
1664 const char *printername, *sharename;
1665 struct rpc_pipe_client *pipe_hnd_dst = NULL;
1666 struct policy_handle hnd_src, hnd_dst;
1667 union spoolss_PrinterInfo *info_enum;
1668 union spoolss_PrinterInfo info_dst;
1669 uint32_t num_forms;
1670 union spoolss_FormInfo *forms;
1671 struct cli_state *cli_dst = NULL;
1673 DEBUG(3,("copying forms\n"));
1675 /* connect destination PI_SPOOLSS */
1676 nt_status = connect_dst_pipe(c, &cli_dst, &pipe_hnd_dst,
1677 &ndr_table_spoolss.syntax_id);
1678 if (!NT_STATUS_IS_OK(nt_status))
1679 return nt_status;
1681 /* enum src printers */
1682 if (!get_printer_info(pipe_hnd, mem_ctx, 2, argc, argv, &num_printers, &info_enum)) {
1683 nt_status = NT_STATUS_UNSUCCESSFUL;
1684 goto done;
1687 if (!num_printers) {
1688 printf (_("no printers found on server.\n"));
1689 nt_status = NT_STATUS_OK;
1690 goto done;
1693 /* do something for all printers */
1694 for (i = 0; i < num_printers; i++) {
1696 /* do some initialization */
1697 printername = info_enum[i].info2.printername;
1698 sharename = info_enum[i].info2.sharename;
1700 if (!printername || !sharename) {
1701 nt_status = NT_STATUS_UNSUCCESSFUL;
1702 goto done;
1704 /* we can reset NT_STATUS here because we do not
1705 get any real NT_STATUS-codes anymore from now on */
1706 nt_status = NT_STATUS_UNSUCCESSFUL;
1708 d_printf(_("migrating printer forms for: [%s] / [%s]\n"),
1709 printername, sharename);
1712 /* open src printer handle */
1713 if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, sharename,
1714 MAXIMUM_ALLOWED_ACCESS, cli->user_name, &hnd_src))
1715 goto done;
1717 /* open dst printer handle */
1718 if (!net_spoolss_open_printer_ex(pipe_hnd_dst, mem_ctx, sharename,
1719 PRINTER_ALL_ACCESS, cli->user_name, &hnd_dst))
1720 goto done;
1722 /* check for existing dst printer */
1723 if (!net_spoolss_getprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, level, &info_dst))
1724 goto done;
1726 /* finally migrate forms */
1727 if (!net_spoolss_enumforms(pipe_hnd, mem_ctx, &hnd_src, level, &num_forms, &forms))
1728 goto done;
1730 DEBUG(1,("got %d forms for printer\n", num_forms));
1733 for (f = 0; f < num_forms; f++) {
1735 union spoolss_AddFormInfo info;
1736 NTSTATUS status;
1738 /* only migrate FORM_PRINTER types, according to jerry
1739 FORM_BUILTIN-types are hard-coded in samba */
1740 if (forms[f].info1.flags != SPOOLSS_FORM_PRINTER)
1741 continue;
1743 if (c->opt_verbose)
1744 d_printf(_("\tmigrating form # %d [%s] of type "
1745 "[%d]\n"),
1746 f, forms[f].info1.form_name,
1747 forms[f].info1.flags);
1749 info.info1 = (struct spoolss_AddFormInfo1 *)
1750 (void *)&forms[f].info1;
1752 /* FIXME: there might be something wrong with samba's
1753 builtin-forms */
1754 status = rpccli_spoolss_AddForm(pipe_hnd_dst, mem_ctx,
1755 &hnd_dst,
1757 info,
1758 &result);
1759 if (!W_ERROR_IS_OK(result)) {
1760 d_printf(_("\tAddForm form %d: [%s] refused.\n"),
1761 f, forms[f].info1.form_name);
1762 continue;
1765 DEBUGADD(1,("\tAddForm of [%s] succeeded\n",
1766 forms[f].info1.form_name));
1770 /* close printer handles here */
1771 if (is_valid_policy_hnd(&hnd_src)) {
1772 rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd_src, NULL);
1775 if (is_valid_policy_hnd(&hnd_dst)) {
1776 rpccli_spoolss_ClosePrinter(pipe_hnd_dst, mem_ctx, &hnd_dst, NULL);
1780 nt_status = NT_STATUS_OK;
1782 done:
1784 if (is_valid_policy_hnd(&hnd_src))
1785 rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd_src, NULL);
1787 if (is_valid_policy_hnd(&hnd_dst))
1788 rpccli_spoolss_ClosePrinter(pipe_hnd_dst, mem_ctx, &hnd_dst, NULL);
1790 if (cli_dst) {
1791 cli_shutdown(cli_dst);
1793 return nt_status;
1797 * Migrate printer-drivers from a src server to the dst server
1799 * All parameters are provided by the run_rpc_command function, except for
1800 * argc, argv which are passed through.
1802 * @param c A net_context structure
1803 * @param domain_sid The domain sid aquired from the remote server
1804 * @param cli A cli_state connected to the server.
1805 * @param mem_ctx Talloc context, destoyed on compleation of the function.
1806 * @param argc Standard main() style argc
1807 * @param argv Standard main() style argv. Initial components are already
1808 * stripped
1810 * @return Normal NTSTATUS return.
1813 NTSTATUS rpc_printer_migrate_drivers_internals(struct net_context *c,
1814 const struct dom_sid *domain_sid,
1815 const char *domain_name,
1816 struct cli_state *cli,
1817 struct rpc_pipe_client *pipe_hnd,
1818 TALLOC_CTX *mem_ctx,
1819 int argc,
1820 const char **argv)
1822 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1823 uint32_t i, p;
1824 uint32_t num_printers;
1825 uint32_t level = 3;
1826 const char *printername, *sharename;
1827 bool got_src_driver_share = false;
1828 bool got_dst_driver_share = false;
1829 struct rpc_pipe_client *pipe_hnd_dst = NULL;
1830 struct policy_handle hnd_src, hnd_dst;
1831 union spoolss_DriverInfo drv_info_src;
1832 union spoolss_PrinterInfo *info_enum;
1833 union spoolss_PrinterInfo info_dst;
1834 struct cli_state *cli_dst = NULL;
1835 struct cli_state *cli_share_src = NULL;
1836 struct cli_state *cli_share_dst = NULL;
1837 const char *drivername = NULL;
1839 DEBUG(3,("copying printer-drivers\n"));
1841 nt_status = connect_dst_pipe(c, &cli_dst, &pipe_hnd_dst,
1842 &ndr_table_spoolss.syntax_id);
1843 if (!NT_STATUS_IS_OK(nt_status))
1844 return nt_status;
1846 /* open print$-share on the src server */
1847 nt_status = connect_to_service(c, &cli_share_src, &cli->dest_ss,
1848 cli->desthost, "print$", "A:");
1849 if (!NT_STATUS_IS_OK(nt_status))
1850 goto done;
1852 got_src_driver_share = true;
1855 /* open print$-share on the dst server */
1856 nt_status = connect_to_service(c, &cli_share_dst, &cli_dst->dest_ss,
1857 cli_dst->desthost, "print$", "A:");
1858 if (!NT_STATUS_IS_OK(nt_status))
1859 return nt_status;
1861 got_dst_driver_share = true;
1864 /* enum src printers */
1865 if (!get_printer_info(pipe_hnd, mem_ctx, 2, argc, argv, &num_printers, &info_enum)) {
1866 nt_status = NT_STATUS_UNSUCCESSFUL;
1867 goto done;
1870 if (num_printers == 0) {
1871 printf (_("no printers found on server.\n"));
1872 nt_status = NT_STATUS_OK;
1873 goto done;
1877 /* do something for all printers */
1878 for (p = 0; p < num_printers; p++) {
1880 /* do some initialization */
1881 printername = info_enum[p].info2.printername;
1882 sharename = info_enum[p].info2.sharename;
1884 if (!printername || !sharename) {
1885 nt_status = NT_STATUS_UNSUCCESSFUL;
1886 goto done;
1889 /* we can reset NT_STATUS here because we do not
1890 get any real NT_STATUS-codes anymore from now on */
1891 nt_status = NT_STATUS_UNSUCCESSFUL;
1893 d_printf(_("migrating printer driver for: [%s] / [%s]\n"),
1894 printername, sharename);
1896 /* open dst printer handle */
1897 if (!net_spoolss_open_printer_ex(pipe_hnd_dst, mem_ctx, sharename,
1898 PRINTER_ALL_ACCESS, cli->user_name, &hnd_dst))
1899 goto done;
1901 /* check for existing dst printer */
1902 if (!net_spoolss_getprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, 2, &info_dst))
1903 goto done;
1906 /* open src printer handle */
1907 if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, sharename,
1908 MAXIMUM_ALLOWED_ACCESS,
1909 pipe_hnd->auth->user_name,
1910 &hnd_src))
1911 goto done;
1913 /* in a first step call getdriver for each shared printer (per arch)
1914 to get a list of all files that have to be copied */
1916 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1918 /* getdriver src */
1919 if (!net_spoolss_getprinterdriver(pipe_hnd, mem_ctx, &hnd_src,
1920 level, archi_table[i].long_archi,
1921 archi_table[i].version, &drv_info_src))
1922 continue;
1924 drivername = drv_info_src.info3.driver_name;
1926 if (c->opt_verbose)
1927 display_print_driver3(&drv_info_src.info3);
1929 /* check arch dir */
1930 nt_status = check_arch_dir(cli_share_dst, archi_table[i].short_archi);
1931 if (!NT_STATUS_IS_OK(nt_status))
1932 goto done;
1935 /* copy driver-files */
1936 nt_status = copy_print_driver_3(c, mem_ctx, cli_share_src, cli_share_dst,
1937 archi_table[i].short_archi,
1938 &drv_info_src.info3);
1939 if (!NT_STATUS_IS_OK(nt_status))
1940 goto done;
1943 /* adddriver dst */
1944 if (!net_spoolss_addprinterdriver(pipe_hnd_dst, mem_ctx, level, &drv_info_src)) {
1945 nt_status = NT_STATUS_UNSUCCESSFUL;
1946 goto done;
1949 DEBUGADD(1,("Sucessfully added driver [%s] for printer [%s]\n",
1950 drivername, printername));
1954 if (!drivername || strlen(drivername) == 0) {
1955 DEBUGADD(1,("Did not get driver for printer %s\n",
1956 printername));
1957 goto done;
1960 /* setdriver dst */
1961 info_dst.info2.drivername = drivername;
1963 if (!net_spoolss_setprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, 2, &info_dst)) {
1964 nt_status = NT_STATUS_UNSUCCESSFUL;
1965 goto done;
1968 DEBUGADD(1,("Sucessfully set driver %s for printer %s\n",
1969 drivername, printername));
1971 /* close dst */
1972 if (is_valid_policy_hnd(&hnd_dst)) {
1973 rpccli_spoolss_ClosePrinter(pipe_hnd_dst, mem_ctx, &hnd_dst, NULL);
1976 /* close src */
1977 if (is_valid_policy_hnd(&hnd_src)) {
1978 rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd_src, NULL);
1982 nt_status = NT_STATUS_OK;
1984 done:
1986 if (is_valid_policy_hnd(&hnd_src))
1987 rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd_src, NULL);
1989 if (is_valid_policy_hnd(&hnd_dst))
1990 rpccli_spoolss_ClosePrinter(pipe_hnd_dst, mem_ctx, &hnd_dst, NULL);
1992 if (cli_dst) {
1993 cli_shutdown(cli_dst);
1996 if (got_src_driver_share)
1997 cli_shutdown(cli_share_src);
1999 if (got_dst_driver_share)
2000 cli_shutdown(cli_share_dst);
2002 return nt_status;
2007 * Migrate printer-queues from a src to the dst server
2008 * (requires a working "addprinter command" to be installed for the local smbd)
2010 * All parameters are provided by the run_rpc_command function, except for
2011 * argc, argv which are passed through.
2013 * @param c A net_context structure
2014 * @param domain_sid The domain sid aquired from the remote server
2015 * @param cli A cli_state connected to the server.
2016 * @param mem_ctx Talloc context, destoyed on compleation of the function.
2017 * @param argc Standard main() style argc
2018 * @param argv Standard main() style argv. Initial components are already
2019 * stripped
2021 * @return Normal NTSTATUS return.
2024 NTSTATUS rpc_printer_migrate_printers_internals(struct net_context *c,
2025 const struct dom_sid *domain_sid,
2026 const char *domain_name,
2027 struct cli_state *cli,
2028 struct rpc_pipe_client *pipe_hnd,
2029 TALLOC_CTX *mem_ctx,
2030 int argc,
2031 const char **argv)
2033 WERROR result;
2034 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
2035 uint32_t i = 0, num_printers;
2036 uint32_t level = 2;
2037 union spoolss_PrinterInfo info_dst, info_src;
2038 union spoolss_PrinterInfo *info_enum;
2039 struct cli_state *cli_dst = NULL;
2040 struct policy_handle hnd_dst, hnd_src;
2041 const char *printername, *sharename;
2042 struct rpc_pipe_client *pipe_hnd_dst = NULL;
2043 struct spoolss_SetPrinterInfoCtr info_ctr;
2045 DEBUG(3,("copying printers\n"));
2047 /* connect destination PI_SPOOLSS */
2048 nt_status = connect_dst_pipe(c, &cli_dst, &pipe_hnd_dst,
2049 &ndr_table_spoolss.syntax_id);
2050 if (!NT_STATUS_IS_OK(nt_status))
2051 return nt_status;
2053 /* enum printers */
2054 if (!get_printer_info(pipe_hnd, mem_ctx, level, argc, argv, &num_printers, &info_enum)) {
2055 nt_status = NT_STATUS_UNSUCCESSFUL;
2056 goto done;
2059 if (!num_printers) {
2060 printf (_("no printers found on server.\n"));
2061 nt_status = NT_STATUS_OK;
2062 goto done;
2065 /* do something for all printers */
2066 for (i = 0; i < num_printers; i++) {
2068 struct spoolss_SetPrinterInfo2 info2;
2070 /* do some initialization */
2071 printername = info_enum[i].info2.printername;
2072 sharename = info_enum[i].info2.sharename;
2074 if (!printername || !sharename) {
2075 nt_status = NT_STATUS_UNSUCCESSFUL;
2076 goto done;
2078 /* we can reset NT_STATUS here because we do not
2079 get any real NT_STATUS-codes anymore from now on */
2080 nt_status = NT_STATUS_UNSUCCESSFUL;
2082 d_printf(_("migrating printer queue for: [%s] / [%s]\n"),
2083 printername, sharename);
2085 /* open dst printer handle */
2086 if (!net_spoolss_open_printer_ex(pipe_hnd_dst, mem_ctx, sharename,
2087 PRINTER_ALL_ACCESS, cli->user_name, &hnd_dst)) {
2089 DEBUG(1,("could not open printer: %s\n", sharename));
2092 /* check for existing dst printer */
2093 if (!net_spoolss_getprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, level, &info_dst)) {
2094 printf (_("could not get printer, creating printer.\n"));
2095 } else {
2096 DEBUG(1,("printer already exists: %s\n", sharename));
2097 /* close printer handle here - dst only, not got src yet. */
2098 if (is_valid_policy_hnd(&hnd_dst)) {
2099 rpccli_spoolss_ClosePrinter(pipe_hnd_dst, mem_ctx, &hnd_dst, NULL);
2101 continue;
2104 /* now get again src printer ctr via getprinter,
2105 we first need a handle for that */
2107 /* open src printer handle */
2108 if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, sharename,
2109 MAXIMUM_ALLOWED_ACCESS, cli->user_name, &hnd_src))
2110 goto done;
2112 /* getprinter on the src server */
2113 if (!net_spoolss_getprinter(pipe_hnd, mem_ctx, &hnd_src, level, &info_src))
2114 goto done;
2116 /* copy each src printer to a dst printer 1:1,
2117 maybe some values have to be changed though */
2118 d_printf(_("creating printer: %s\n"), printername);
2120 info_ctr.level = level;
2121 spoolss_printerinfo2_to_setprinterinfo2(&info_src.info2, &info2);
2122 info_ctr.info.info2 = &info2;
2124 result = rpccli_spoolss_addprinterex(pipe_hnd_dst,
2125 mem_ctx,
2126 &info_ctr);
2128 if (W_ERROR_IS_OK(result))
2129 d_printf (_("printer [%s] successfully added.\n"),
2130 printername);
2131 else if (W_ERROR_V(result) == W_ERROR_V(WERR_PRINTER_ALREADY_EXISTS))
2132 d_fprintf (stderr, _("printer [%s] already exists.\n"),
2133 printername);
2134 else {
2135 d_fprintf (stderr, _("could not create printer [%s]\n"),
2136 printername);
2137 goto done;
2140 /* close printer handles here */
2141 if (is_valid_policy_hnd(&hnd_src)) {
2142 rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd_src, NULL);
2145 if (is_valid_policy_hnd(&hnd_dst)) {
2146 rpccli_spoolss_ClosePrinter(pipe_hnd_dst, mem_ctx, &hnd_dst, NULL);
2150 nt_status = NT_STATUS_OK;
2152 done:
2153 if (is_valid_policy_hnd(&hnd_src))
2154 rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd_src, NULL);
2156 if (is_valid_policy_hnd(&hnd_dst))
2157 rpccli_spoolss_ClosePrinter(pipe_hnd_dst, mem_ctx, &hnd_dst, NULL);
2159 if (cli_dst) {
2160 cli_shutdown(cli_dst);
2162 return nt_status;
2166 * Migrate Printer-Settings from a src server to the dst server
2167 * (for this to work, printers and drivers already have to be migrated earlier)
2169 * All parameters are provided by the run_rpc_command function, except for
2170 * argc, argv which are passed through.
2172 * @param c A net_context structure
2173 * @param domain_sid The domain sid aquired from the remote server
2174 * @param cli A cli_state connected to the server.
2175 * @param mem_ctx Talloc context, destoyed on compleation of the function.
2176 * @param argc Standard main() style argc
2177 * @param argv Standard main() style argv. Initial components are already
2178 * stripped
2180 * @return Normal NTSTATUS return.
2183 NTSTATUS rpc_printer_migrate_settings_internals(struct net_context *c,
2184 const struct dom_sid *domain_sid,
2185 const char *domain_name,
2186 struct cli_state *cli,
2187 struct rpc_pipe_client *pipe_hnd,
2188 TALLOC_CTX *mem_ctx,
2189 int argc,
2190 const char **argv)
2193 /* FIXME: Here the nightmare begins */
2195 WERROR result;
2196 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
2197 uint32_t i = 0, p = 0, j = 0;
2198 uint32_t num_printers;
2199 uint32_t level = 2;
2200 const char *printername, *sharename;
2201 struct rpc_pipe_client *pipe_hnd_dst = NULL;
2202 struct policy_handle hnd_src, hnd_dst;
2203 union spoolss_PrinterInfo *info_enum;
2204 union spoolss_PrinterInfo info_dst_publish;
2205 union spoolss_PrinterInfo info_dst;
2206 struct cli_state *cli_dst = NULL;
2207 char *devicename = NULL, *unc_name = NULL, *url = NULL;
2208 const char *longname;
2209 const char **keylist = NULL;
2211 /* FIXME GD */
2212 ZERO_STRUCT(info_dst_publish);
2214 DEBUG(3,("copying printer settings\n"));
2216 /* connect destination PI_SPOOLSS */
2217 nt_status = connect_dst_pipe(c, &cli_dst, &pipe_hnd_dst,
2218 &ndr_table_spoolss.syntax_id);
2219 if (!NT_STATUS_IS_OK(nt_status))
2220 return nt_status;
2222 /* enum src printers */
2223 if (!get_printer_info(pipe_hnd, mem_ctx, level, argc, argv, &num_printers, &info_enum)) {
2224 nt_status = NT_STATUS_UNSUCCESSFUL;
2225 goto done;
2228 if (!num_printers) {
2229 printf (_("no printers found on server.\n"));
2230 nt_status = NT_STATUS_OK;
2231 goto done;
2235 /* needed for dns-strings in regkeys */
2236 longname = get_mydnsfullname();
2237 if (!longname) {
2238 nt_status = NT_STATUS_UNSUCCESSFUL;
2239 goto done;
2242 /* do something for all printers */
2243 for (i = 0; i < num_printers; i++) {
2245 uint32_t value_offered = 0, value_needed;
2246 uint32_t data_offered = 0, data_needed;
2247 enum winreg_Type type;
2248 uint8_t *buffer = NULL;
2249 const char *value_name = NULL;
2251 /* do some initialization */
2252 printername = info_enum[i].info2.printername;
2253 sharename = info_enum[i].info2.sharename;
2255 if (!printername || !sharename) {
2256 nt_status = NT_STATUS_UNSUCCESSFUL;
2257 goto done;
2259 /* we can reset NT_STATUS here because we do not
2260 get any real NT_STATUS-codes anymore from now on */
2261 nt_status = NT_STATUS_UNSUCCESSFUL;
2263 d_printf(_("migrating printer settings for: [%s] / [%s]\n"),
2264 printername, sharename);
2267 /* open src printer handle */
2268 if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, sharename,
2269 MAXIMUM_ALLOWED_ACCESS, cli->user_name, &hnd_src))
2270 goto done;
2272 /* open dst printer handle */
2273 if (!net_spoolss_open_printer_ex(pipe_hnd_dst, mem_ctx, sharename,
2274 PRINTER_ALL_ACCESS, cli_dst->user_name, &hnd_dst))
2275 goto done;
2277 /* check for existing dst printer */
2278 if (!net_spoolss_getprinter(pipe_hnd_dst, mem_ctx, &hnd_dst,
2279 level, &info_dst))
2280 goto done;
2283 /* STEP 1: COPY DEVICE-MODE and other
2284 PRINTER_INFO_2-attributes
2287 info_dst.info2 = info_enum[i].info2;
2289 /* why is the port always disconnected when the printer
2290 is correctly installed (incl. driver ???) */
2291 info_dst.info2.portname = SAMBA_PRINTER_PORT_NAME;
2293 /* check if printer is published */
2294 if (info_enum[i].info2.attributes & PRINTER_ATTRIBUTE_PUBLISHED) {
2296 /* check for existing dst printer */
2297 if (!net_spoolss_getprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, 7, &info_dst_publish))
2298 goto done;
2300 info_dst_publish.info7.action = DSPRINT_PUBLISH;
2302 /* ignore false from setprinter due to WERR_IO_PENDING */
2303 net_spoolss_setprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, 7, &info_dst_publish);
2305 DEBUG(3,("republished printer\n"));
2308 if (info_enum[i].info2.devmode != NULL) {
2310 /* copy devmode (info level 2) */
2311 info_dst.info2.devmode = info_enum[i].info2.devmode;
2313 /* do not copy security descriptor (we have another
2314 * command for that) */
2315 info_dst.info2.secdesc = NULL;
2317 #if 0
2318 info_dst.info2.devmode.devicename =
2319 talloc_asprintf(mem_ctx, "\\\\%s\\%s",
2320 longname, printername);
2321 if (!info_dst.info2.devmode.devicename) {
2322 nt_status = NT_STATUS_NO_MEMORY;
2323 goto done;
2325 #endif
2326 if (!net_spoolss_setprinter(pipe_hnd_dst, mem_ctx, &hnd_dst,
2327 level, &info_dst))
2328 goto done;
2330 DEBUGADD(1,("\tSetPrinter of DEVICEMODE succeeded\n"));
2333 /* STEP 2: COPY REGISTRY VALUES */
2335 /* please keep in mind that samba parse_spools gives horribly
2336 crippled results when used to rpccli_spoolss_enumprinterdataex
2337 a win2k3-server. (Bugzilla #1851)
2338 FIXME: IIRC I've seen it too on a win2k-server
2341 /* enumerate data on src handle */
2342 nt_status = rpccli_spoolss_EnumPrinterData(pipe_hnd, mem_ctx,
2343 &hnd_src,
2345 value_name,
2346 value_offered,
2347 &value_needed,
2348 &type,
2349 buffer,
2350 data_offered,
2351 &data_needed,
2352 &result);
2354 data_offered = data_needed;
2355 value_offered = value_needed;
2356 buffer = talloc_zero_array(mem_ctx, uint8_t, data_needed);
2357 value_name = talloc_zero_array(mem_ctx, char, value_needed);
2359 /* loop for all printerdata of "PrinterDriverData" */
2360 while (NT_STATUS_IS_OK(nt_status) && W_ERROR_IS_OK(result)) {
2362 nt_status = rpccli_spoolss_EnumPrinterData(pipe_hnd, mem_ctx,
2363 &hnd_src,
2364 p++,
2365 value_name,
2366 value_offered,
2367 &value_needed,
2368 &type,
2369 buffer,
2370 data_offered,
2371 &data_needed,
2372 &result);
2373 /* loop for all reg_keys */
2374 if (NT_STATUS_IS_OK(nt_status) && W_ERROR_IS_OK(result)) {
2376 /* display_value */
2377 if (c->opt_verbose) {
2378 struct regval_blob *v;
2380 v = regval_compose(talloc_tos(),
2381 value_name,
2382 type,
2383 buffer,
2384 data_offered);
2385 if (v == NULL) {
2386 nt_status = NT_STATUS_NO_MEMORY;
2387 goto done;
2390 display_reg_value(SPOOL_PRINTERDATA_KEY, v);
2391 talloc_free(v);
2394 /* set_value */
2395 if (!net_spoolss_setprinterdata(pipe_hnd_dst, mem_ctx,
2396 &hnd_dst, value_name,
2397 type, buffer, data_offered))
2398 goto done;
2400 DEBUGADD(1,("\tSetPrinterData of [%s] succeeded\n",
2401 value_name));
2405 /* STEP 3: COPY SUBKEY VALUES */
2407 /* here we need to enum all printer_keys and then work
2408 on the result with enum_printer_key_ex. nt4 does not
2409 respond to enumprinterkey, win2k does, so continue
2410 in case of an error */
2412 if (!net_spoolss_enumprinterkey(pipe_hnd, mem_ctx, &hnd_src, "", &keylist)) {
2413 printf(_("got no key-data\n"));
2414 continue;
2418 /* work on a list of printer keys
2419 each key has to be enumerated to get all required
2420 information. information is then set via setprinterdataex-calls */
2422 if (keylist == NULL)
2423 continue;
2425 for (i=0; keylist && keylist[i] != NULL; i++) {
2427 const char *subkey = keylist[i];
2428 uint32_t count;
2429 struct spoolss_PrinterEnumValues *info;
2431 /* enumerate all src subkeys */
2432 if (!net_spoolss_enumprinterdataex(pipe_hnd, mem_ctx, 0,
2433 &hnd_src, subkey,
2434 &count, &info)) {
2435 goto done;
2438 for (j=0; j < count; j++) {
2440 struct regval_blob *value;
2441 DATA_BLOB blob;
2443 ZERO_STRUCT(blob);
2445 /* although samba replies with sane data in most cases we
2446 should try to avoid writing wrong registry data */
2448 if (strequal(info[j].value_name, SPOOL_REG_PORTNAME) ||
2449 strequal(info[j].value_name, SPOOL_REG_UNCNAME) ||
2450 strequal(info[j].value_name, SPOOL_REG_URL) ||
2451 strequal(info[j].value_name, SPOOL_REG_SHORTSERVERNAME) ||
2452 strequal(info[j].value_name, SPOOL_REG_SERVERNAME)) {
2454 if (strequal(info[j].value_name, SPOOL_REG_PORTNAME)) {
2456 /* although windows uses a multi-sz, we use a sz */
2457 push_reg_sz(mem_ctx, &blob, SAMBA_PRINTER_PORT_NAME);
2460 if (strequal(info[j].value_name, SPOOL_REG_UNCNAME)) {
2462 if (asprintf(&unc_name, "\\\\%s\\%s", longname, sharename) < 0) {
2463 nt_status = NT_STATUS_NO_MEMORY;
2464 goto done;
2466 push_reg_sz(mem_ctx, &blob, unc_name);
2469 if (strequal(info[j].value_name, SPOOL_REG_URL)) {
2471 continue;
2473 #if 0
2474 /* FIXME: should we really do that ??? */
2475 if (asprintf(&url, "http://%s:631/printers/%s", longname, sharename) < 0) {
2476 nt_status = NT_STATUS_NO_MEMORY;
2477 goto done;
2479 push_reg_sz(mem_ctx, NULL, &blob, url);
2480 fstrcpy(value.valuename, SPOOL_REG_URL);
2481 #endif
2484 if (strequal(info[j].value_name, SPOOL_REG_SERVERNAME)) {
2486 push_reg_sz(mem_ctx, &blob, longname);
2489 if (strequal(info[j].value_name, SPOOL_REG_SHORTSERVERNAME)) {
2491 push_reg_sz(mem_ctx, &blob, global_myname());
2494 value = regval_compose(talloc_tos(),
2495 info[j].value_name,
2496 REG_SZ,
2497 blob.length == 0 ? NULL : blob.data,
2498 blob.length);
2499 if (value == NULL) {
2500 nt_status = NT_STATUS_NO_MEMORY;
2501 goto done;
2504 if (c->opt_verbose)
2505 display_reg_value(subkey, value);
2507 /* here we have to set all subkeys on the dst server */
2508 if (!net_spoolss_setprinterdataex(pipe_hnd_dst, mem_ctx, &hnd_dst,
2509 subkey, value))
2511 talloc_free(value);
2512 goto done;
2515 talloc_free(value);
2516 } else {
2518 struct regval_blob *v;
2520 v = regval_compose(talloc_tos(),
2521 info[j].value_name,
2522 info[j].type,
2523 info[j].data->data,
2524 info[j].data->length);
2525 if (v == NULL) {
2526 nt_status = NT_STATUS_NO_MEMORY;
2527 goto done;
2530 if (c->opt_verbose) {
2531 display_reg_value(subkey, v);
2534 /* here we have to set all subkeys on the dst server */
2535 if (!net_spoolss_setprinterdataex(pipe_hnd_dst, mem_ctx, &hnd_dst,
2536 subkey, v)) {
2537 goto done;
2540 talloc_free(v);
2543 DEBUGADD(1,("\tSetPrinterDataEx of key [%s\\%s] succeeded\n",
2544 subkey, info[j].value_name));
2549 TALLOC_FREE(keylist);
2551 /* close printer handles here */
2552 if (is_valid_policy_hnd(&hnd_src)) {
2553 rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd_src, NULL);
2556 if (is_valid_policy_hnd(&hnd_dst)) {
2557 rpccli_spoolss_ClosePrinter(pipe_hnd_dst, mem_ctx, &hnd_dst, NULL);
2562 nt_status = NT_STATUS_OK;
2564 done:
2565 SAFE_FREE(devicename);
2566 SAFE_FREE(url);
2567 SAFE_FREE(unc_name);
2569 if (is_valid_policy_hnd(&hnd_src))
2570 rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd_src, NULL);
2572 if (is_valid_policy_hnd(&hnd_dst))
2573 rpccli_spoolss_ClosePrinter(pipe_hnd_dst, mem_ctx, &hnd_dst, NULL);
2575 if (cli_dst) {
2576 cli_shutdown(cli_dst);
2578 return nt_status;