s3: Fix Coverity ID 2296: UNUSED_VALUE
[Samba.git] / source3 / utils / net_rpc_printer.c
blob8be4fb145c249651c228bdf3cc0f61bc4f9902fc
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/ndr_spoolss_c.h"
22 #include "rpc_client/cli_spoolss.h"
23 #include "rpc_client/init_spoolss.h"
24 #include "nt_printing.h"
25 #include "registry/reg_objects.h"
26 #include "../libcli/security/security.h"
28 /* support itanium as well */
29 static const struct print_architecture_table_node archi_table[]= {
31 {"Windows 4.0", "WIN40", 0 },
32 {"Windows NT x86", "W32X86", 2 },
33 {"Windows NT x86", "W32X86", 3 },
34 {"Windows NT R4000", "W32MIPS", 2 },
35 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
36 {"Windows NT PowerPC", "W32PPC", 2 },
37 {"Windows IA64", "IA64", 3 },
38 {"Windows x64", "x64", 3 },
39 {NULL, "", -1 }
43 /**
44 * This display-printdriver-functions was borrowed from rpcclient/cmd_spoolss.c.
45 * It is here for debugging purpose and should be removed later on.
46 **/
48 /****************************************************************************
49 Printer info level 3 display function.
50 ****************************************************************************/
52 static void display_print_driver3(struct spoolss_DriverInfo3 *r)
54 int i;
56 if (!r) {
57 return;
60 printf(_("Printer Driver Info 3:\n"));
61 printf(_("\tVersion: [%x]\n"), r->version);
62 printf(_("\tDriver Name: [%s]\n"), r->driver_name);
63 printf(_("\tArchitecture: [%s]\n"), r->architecture);
64 printf(_("\tDriver Path: [%s]\n"), r->driver_path);
65 printf(_("\tDatafile: [%s]\n"), r->data_file);
66 printf(_("\tConfigfile: [%s]\n\n"), r->config_file);
67 printf(_("\tHelpfile: [%s]\n\n"), r->help_file);
69 for (i=0; r->dependent_files[i] != NULL; i++) {
70 printf(_("\tDependentfiles: [%s]\n"), r->dependent_files[i]);
73 printf("\n");
75 printf(_("\tMonitorname: [%s]\n"), r->monitor_name);
76 printf(_("\tDefaultdatatype: [%s]\n\n"), r->default_datatype);
79 static void display_reg_value(const char *subkey, struct regval_blob *value)
81 const char *text;
82 DATA_BLOB blob;
84 switch(regval_type(value)) {
85 case REG_DWORD:
86 d_printf(_("\t[%s:%s]: REG_DWORD: 0x%08x\n"), subkey,
87 regval_name(value), *((uint32_t *) regval_data_p(value)));
88 break;
90 case REG_SZ:
91 blob = data_blob_const(regval_data_p(value), regval_size(value));
92 pull_reg_sz(talloc_tos(), &blob, &text);
93 if (!text) {
94 break;
96 d_printf(_("\t[%s:%s]: REG_SZ: %s\n"), subkey, regval_name(value),
97 text);
98 break;
100 case REG_BINARY:
101 d_printf(_("\t[%s:%s]: REG_BINARY: unknown length value not "
102 "displayed\n"),
103 subkey, regval_name(value));
104 break;
106 case REG_MULTI_SZ: {
107 uint32_t i;
108 const char **values;
109 blob = data_blob_const(regval_data_p(value), regval_size(value));
111 if (!pull_reg_multi_sz(NULL, &blob, &values)) {
112 d_printf("pull_reg_multi_sz failed\n");
113 break;
116 printf("%s: REG_MULTI_SZ: \n", regval_name(value));
117 for (i=0; values[i] != NULL; i++) {
118 d_printf("%s\n", values[i]);
120 TALLOC_FREE(values);
121 break;
124 default:
125 d_printf(_("\t%s: unknown type %d\n"), regval_name(value),
126 regval_type(value));
132 * Copies ACLs, DOS-attributes and timestamps from one
133 * file or directory from one connected share to another connected share
135 * @param c A net_context structure
136 * @param mem_ctx A talloc-context
137 * @param cli_share_src A connected cli_state
138 * @param cli_share_dst A connected cli_state
139 * @param src_file The source file-name
140 * @param dst_file The destination file-name
141 * @param copy_acls Whether to copy acls
142 * @param copy_attrs Whether to copy DOS attributes
143 * @param copy_timestamps Whether to preserve timestamps
144 * @param is_file Whether this file is a file or a dir
146 * @return Normal NTSTATUS return.
149 NTSTATUS net_copy_fileattr(struct net_context *c,
150 TALLOC_CTX *mem_ctx,
151 struct cli_state *cli_share_src,
152 struct cli_state *cli_share_dst,
153 const char *src_name, const char *dst_name,
154 bool copy_acls, bool copy_attrs,
155 bool copy_timestamps, bool is_file)
157 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
158 uint16_t fnum_src = 0;
159 uint16_t fnum_dst = 0;
160 struct security_descriptor *sd = NULL;
161 uint16_t attr;
162 time_t f_atime, f_ctime, f_mtime;
165 if (!copy_timestamps && !copy_acls && !copy_attrs)
166 return NT_STATUS_OK;
168 /* open file/dir on the originating server */
170 DEBUGADD(3,("opening %s %s on originating server\n",
171 is_file?"file":"dir", src_name));
173 if (!NT_STATUS_IS_OK(cli_ntcreate(cli_share_src, src_name, 0, READ_CONTROL_ACCESS, 0,
174 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0x0, 0x0, &fnum_src))) {
175 DEBUGADD(0,("cannot open %s %s on originating server %s\n",
176 is_file?"file":"dir", src_name, cli_errstr(cli_share_src)));
177 nt_status = cli_nt_error(cli_share_src);
178 goto out;
182 if (copy_acls) {
184 /* get the security descriptor */
185 sd = cli_query_secdesc(cli_share_src, fnum_src, mem_ctx);
186 if (!sd) {
187 DEBUG(0,("failed to get security descriptor: %s\n",
188 cli_errstr(cli_share_src)));
189 nt_status = cli_nt_error(cli_share_src);
190 goto out;
193 if (c->opt_verbose && DEBUGLEVEL >= 3)
194 display_sec_desc(sd);
198 if (copy_attrs || copy_timestamps) {
200 /* get file attributes */
201 if (!NT_STATUS_IS_OK(cli_getattrE(cli_share_src, fnum_src, &attr, NULL,
202 &f_ctime, &f_atime, &f_mtime))) {
203 DEBUG(0,("failed to get file-attrs: %s\n",
204 cli_errstr(cli_share_src)));
205 nt_status = cli_nt_error(cli_share_src);
206 goto out;
211 /* open the file/dir on the destination server */
213 if (!NT_STATUS_IS_OK(cli_ntcreate(cli_share_dst, dst_name, 0, WRITE_DAC_ACCESS | WRITE_OWNER_ACCESS, 0,
214 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0x0, 0x0, &fnum_dst))) {
215 DEBUG(0,("failed to open %s on the destination server: %s: %s\n",
216 is_file?"file":"dir", dst_name, cli_errstr(cli_share_dst)));
217 nt_status = cli_nt_error(cli_share_dst);
218 goto out;
221 if (copy_timestamps) {
223 /* set timestamps */
224 if (!NT_STATUS_IS_OK(cli_setattrE(cli_share_dst, fnum_dst, f_ctime, f_atime, f_mtime))) {
225 DEBUG(0,("failed to set file-attrs (timestamps): %s\n",
226 cli_errstr(cli_share_dst)));
227 nt_status = cli_nt_error(cli_share_dst);
228 goto out;
232 if (copy_acls) {
233 NTSTATUS status;
235 /* set acls */
236 status = cli_set_secdesc(cli_share_dst, fnum_dst, sd);
237 if (!NT_STATUS_IS_OK(status)) {
238 DEBUG(0, ("could not set secdesc on %s: %s\n",
239 dst_name, nt_errstr(status)));
240 nt_status = status;
241 goto out;
245 if (copy_attrs) {
247 /* set attrs */
248 if (!NT_STATUS_IS_OK(cli_setatr(cli_share_dst, dst_name, attr, 0))) {
249 DEBUG(0,("failed to set file-attrs: %s\n",
250 cli_errstr(cli_share_dst)));
251 nt_status = cli_nt_error(cli_share_dst);
252 goto out;
257 /* closing files */
259 if (!NT_STATUS_IS_OK(cli_close(cli_share_src, fnum_src))) {
260 d_fprintf(stderr,
261 _("could not close %s on originating server: %s\n"),
262 is_file?"file":"dir", cli_errstr(cli_share_src));
263 nt_status = cli_nt_error(cli_share_src);
264 goto out;
267 if (!NT_STATUS_IS_OK(cli_close(cli_share_dst, fnum_dst))) {
268 d_fprintf(stderr,
269 _("could not close %s on destination server: %s\n"),
270 is_file?"file":"dir", cli_errstr(cli_share_dst));
271 nt_status = cli_nt_error(cli_share_dst);
272 goto out;
276 nt_status = NT_STATUS_OK;
278 out:
280 /* cleaning up */
281 if (fnum_src)
282 cli_close(cli_share_src, fnum_src);
284 if (fnum_dst)
285 cli_close(cli_share_dst, fnum_dst);
287 return nt_status;
291 * Copy a file or directory from a connected share to another connected share
293 * @param c A net_context structure
294 * @param mem_ctx A talloc-context
295 * @param cli_share_src A connected cli_state
296 * @param cli_share_dst A connected cli_state
297 * @param src_file The source file-name
298 * @param dst_file The destination file-name
299 * @param copy_acls Whether to copy acls
300 * @param copy_attrs Whether to copy DOS attributes
301 * @param copy_timestamps Whether to preserve timestamps
302 * @param is_file Whether this file is a file or a dir
304 * @return Normal NTSTATUS return.
307 NTSTATUS net_copy_file(struct net_context *c,
308 TALLOC_CTX *mem_ctx,
309 struct cli_state *cli_share_src,
310 struct cli_state *cli_share_dst,
311 const char *src_name, const char *dst_name,
312 bool copy_acls, bool copy_attrs,
313 bool copy_timestamps, bool is_file)
315 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
316 uint16_t fnum_src = 0;
317 uint16_t fnum_dst = 0;
318 static int io_bufsize = 64512;
319 int read_size = io_bufsize;
320 char *data = NULL;
321 off_t nread = 0;
324 if (!src_name || !dst_name)
325 goto out;
327 if (cli_share_src == NULL || cli_share_dst == NULL)
328 goto out;
330 /* open on the originating server */
331 DEBUGADD(3,("opening %s %s on originating server\n",
332 is_file ? "file":"dir", src_name));
333 if (is_file)
334 nt_status = cli_open(cli_share_src, src_name, O_RDONLY, DENY_NONE, &fnum_src);
335 else
336 nt_status = cli_ntcreate(cli_share_src, src_name, 0, READ_CONTROL_ACCESS, 0,
337 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0x0, 0x0, &fnum_src);
339 if (!NT_STATUS_IS_OK(nt_status)) {
340 DEBUGADD(0,("cannot open %s %s on originating server %s\n",
341 is_file ? "file":"dir",
342 src_name, cli_errstr(cli_share_src)));
343 goto out;
347 if (is_file) {
349 /* open file on the destination server */
350 DEBUGADD(3,("opening file %s on destination server\n", dst_name));
351 nt_status = cli_open(cli_share_dst, dst_name,
352 O_RDWR|O_CREAT|O_TRUNC, DENY_NONE, &fnum_dst);
354 if (!NT_STATUS_IS_OK(nt_status)) {
355 DEBUGADD(1,("cannot create file %s on destination server: %s\n",
356 dst_name, cli_errstr(cli_share_dst)));
357 goto out;
360 /* allocate memory */
361 if (!(data = (char *)SMB_MALLOC(read_size))) {
362 d_fprintf(stderr, _("malloc fail for size %d\n"),
363 read_size);
364 nt_status = NT_STATUS_NO_MEMORY;
365 goto out;
371 if (c->opt_verbose) {
373 d_printf(_("copying [\\\\%s\\%s%s] => [\\\\%s\\%s%s] "
374 "%s ACLs and %s DOS Attributes %s\n"),
375 cli_share_src->desthost, cli_share_src->share, src_name,
376 cli_share_dst->desthost, cli_share_dst->share, dst_name,
377 copy_acls ? _("with") : _("without"),
378 copy_attrs ? _("with") : _("without"),
379 copy_timestamps ? _("(preserving timestamps)") : "" );
383 while (is_file) {
385 /* copying file */
386 int n, ret;
387 n = cli_read(cli_share_src, fnum_src, data, nread,
388 read_size);
390 if (n <= 0)
391 break;
393 ret = cli_write(cli_share_dst, fnum_dst, 0, data,
394 nread, n);
396 if (n != ret) {
397 d_fprintf(stderr, _("Error writing file: %s\n"),
398 cli_errstr(cli_share_dst));
399 nt_status = cli_nt_error(cli_share_dst);
400 goto out;
403 nread += n;
407 if (!is_file && !NT_STATUS_IS_OK(cli_chkpath(cli_share_dst, dst_name))) {
409 /* creating dir */
410 DEBUGADD(3,("creating dir %s on the destination server\n",
411 dst_name));
413 if (!NT_STATUS_IS_OK(cli_mkdir(cli_share_dst, dst_name))) {
414 DEBUG(0,("cannot create directory %s: %s\n",
415 dst_name, cli_errstr(cli_share_dst)));
416 nt_status = NT_STATUS_NO_SUCH_FILE;
419 if (!NT_STATUS_IS_OK(cli_chkpath(cli_share_dst, dst_name))) {
420 d_fprintf(stderr,
421 _("cannot check for directory %s: %s\n"),
422 dst_name, cli_errstr(cli_share_dst));
423 goto out;
428 /* closing files */
429 if (!NT_STATUS_IS_OK(cli_close(cli_share_src, fnum_src))) {
430 d_fprintf(stderr,
431 _("could not close file on originating server: %s\n"),
432 cli_errstr(cli_share_src));
433 nt_status = cli_nt_error(cli_share_src);
434 goto out;
437 if (is_file && !NT_STATUS_IS_OK(cli_close(cli_share_dst, fnum_dst))) {
438 d_fprintf(stderr,
439 _("could not close file on destination server: %s\n"),
440 cli_errstr(cli_share_dst));
441 nt_status = cli_nt_error(cli_share_dst);
442 goto out;
445 /* possibly we have to copy some file-attributes / acls / sd */
446 nt_status = net_copy_fileattr(c, mem_ctx, cli_share_src, cli_share_dst,
447 src_name, dst_name, copy_acls,
448 copy_attrs, copy_timestamps, is_file);
449 if (!NT_STATUS_IS_OK(nt_status))
450 goto out;
453 nt_status = NT_STATUS_OK;
455 out:
457 /* cleaning up */
458 if (fnum_src)
459 cli_close(cli_share_src, fnum_src);
461 if (fnum_dst)
462 cli_close(cli_share_dst, fnum_dst);
464 SAFE_FREE(data);
466 return nt_status;
470 * Copy a driverfile from on connected share to another connected share
471 * This silently assumes that a driver-file is picked up from
473 * \\src_server\print$\{arch}\{version}\file
475 * and copied to
477 * \\dst_server\print$\{arch}\file
479 * to be added via setdriver-calls later.
480 * @param c A net_context structure
481 * @param mem_ctx A talloc-context
482 * @param cli_share_src A cli_state connected to source print$-share
483 * @param cli_share_dst A cli_state connected to destination print$-share
484 * @param file The file-name to be copied
485 * @param short_archi The name of the driver-architecture (short form)
487 * @return Normal NTSTATUS return.
490 static NTSTATUS net_copy_driverfile(struct net_context *c,
491 TALLOC_CTX *mem_ctx,
492 struct cli_state *cli_share_src,
493 struct cli_state *cli_share_dst,
494 const char *file, const char *short_archi) {
496 const char *p;
497 char *src_name;
498 char *dst_name;
499 char *version = NULL;
500 char *filename = NULL;
501 char *tok;
503 if (!file) {
504 return NT_STATUS_OK;
507 /* scroll through the file until we have the part
508 beyond archi_table.short_archi */
509 p = file;
510 while (next_token_talloc(mem_ctx, &p, &tok, "\\")) {
511 if (strequal(tok, short_archi)) {
512 next_token_talloc(mem_ctx, &p, &version, "\\");
513 next_token_talloc(mem_ctx, &p, &filename, "\\");
517 if (version == NULL || filename == NULL) {
518 return NT_STATUS_UNSUCCESSFUL;
521 /* build source file name */
522 src_name = talloc_asprintf(mem_ctx, "\\%s\\%s\\%s",
523 short_archi, version, filename);
524 if (src_name == NULL) {
525 return NT_STATUS_NO_MEMORY;
528 /* create destination file name */
529 dst_name = talloc_asprintf(mem_ctx, "\\%s\\%s", short_archi, filename);
530 if (dst_name == NULL) {
531 return NT_STATUS_NO_MEMORY;
535 /* finally copy the file */
536 return net_copy_file(c, mem_ctx, cli_share_src, cli_share_dst,
537 src_name, dst_name, false, false, false, true);
541 * Check for existing Architecture directory on a given server
543 * @param cli_share A cli_state connected to a print$-share
544 * @param short_archi The Architecture for the print-driver
546 * @return Normal NTSTATUS return.
549 static NTSTATUS check_arch_dir(struct cli_state *cli_share, const char *short_archi)
552 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
553 char *dir;
555 if (asprintf(&dir, "\\%s", short_archi) < 0) {
556 return NT_STATUS_NO_MEMORY;
559 DEBUG(10,("creating print-driver dir for architecture: %s\n",
560 short_archi));
562 if (!NT_STATUS_IS_OK(cli_mkdir(cli_share, dir))) {
563 DEBUG(1,("cannot create directory %s: %s\n",
564 dir, cli_errstr(cli_share)));
565 nt_status = NT_STATUS_NO_SUCH_FILE;
568 if (!NT_STATUS_IS_OK(cli_chkpath(cli_share, dir))) {
569 d_fprintf(stderr, _("cannot check %s: %s\n"),
570 dir, cli_errstr(cli_share));
571 goto out;
574 nt_status = NT_STATUS_OK;
576 out:
577 SAFE_FREE(dir);
578 return nt_status;
582 * Copy a print-driver (level 3) from one connected print$-share to another
583 * connected print$-share
585 * @param c A net_context structure
586 * @param mem_ctx A talloc-context
587 * @param cli_share_src A cli_state connected to a print$-share
588 * @param cli_share_dst A cli_state connected to a print$-share
589 * @param short_archi The Architecture for the print-driver
590 * @param i1 The DRIVER_INFO_3-struct
592 * @return Normal NTSTATUS return.
595 static NTSTATUS copy_print_driver_3(struct net_context *c,
596 TALLOC_CTX *mem_ctx,
597 struct cli_state *cli_share_src,
598 struct cli_state *cli_share_dst,
599 const char *short_archi,
600 struct spoolss_DriverInfo3 *r)
602 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
603 int i;
605 if (r == NULL) {
606 return nt_status;
609 if (c->opt_verbose)
610 d_printf(_("copying driver: [%s], for architecture: [%s], "
611 "version: [%d]\n"),
612 r->driver_name, short_archi, r->version);
614 nt_status = net_copy_driverfile(c, mem_ctx, cli_share_src, cli_share_dst,
615 r->driver_path, short_archi);
616 if (!NT_STATUS_IS_OK(nt_status))
617 return nt_status;
619 nt_status = net_copy_driverfile(c, mem_ctx, cli_share_src, cli_share_dst,
620 r->data_file, short_archi);
621 if (!NT_STATUS_IS_OK(nt_status))
622 return nt_status;
624 nt_status = net_copy_driverfile(c, mem_ctx, cli_share_src, cli_share_dst,
625 r->config_file, short_archi);
626 if (!NT_STATUS_IS_OK(nt_status))
627 return nt_status;
629 nt_status = net_copy_driverfile(c, mem_ctx, cli_share_src, cli_share_dst,
630 r->help_file, short_archi);
631 if (!NT_STATUS_IS_OK(nt_status))
632 return nt_status;
634 for (i=0; r->dependent_files[i] != NULL; i++) {
636 nt_status = net_copy_driverfile(c, mem_ctx,
637 cli_share_src, cli_share_dst,
638 r->dependent_files[i], short_archi);
639 if (!NT_STATUS_IS_OK(nt_status)) {
640 return nt_status;
644 return NT_STATUS_OK;
648 * net_spoolss-functions
649 * =====================
651 * the net_spoolss-functions aim to simplify spoolss-client-functions
652 * required during the migration-process wrt buffer-sizes, returned
653 * error-codes, etc.
655 * this greatly reduces the complexitiy of the migrate-functions.
659 static bool net_spoolss_enum_printers(struct rpc_pipe_client *pipe_hnd,
660 TALLOC_CTX *mem_ctx,
661 char *name,
662 uint32_t flags,
663 uint32_t level,
664 uint32_t *num_printers,
665 union spoolss_PrinterInfo **info)
667 WERROR result;
669 /* enum printers */
671 result = rpccli_spoolss_enumprinters(pipe_hnd, mem_ctx,
672 flags,
673 name,
674 level,
676 num_printers,
677 info);
678 if (!W_ERROR_IS_OK(result)) {
679 printf(_("cannot enum printers: %s\n"), win_errstr(result));
680 return false;
683 return true;
686 static bool net_spoolss_open_printer_ex(struct rpc_pipe_client *pipe_hnd,
687 TALLOC_CTX *mem_ctx,
688 const char *printername,
689 uint32_t access_required,
690 const char *username,
691 struct policy_handle *hnd)
693 WERROR result;
694 fstring printername2;
696 fstrcpy(printername2, pipe_hnd->srv_name_slash);
697 fstrcat(printername2, "\\");
698 fstrcat(printername2, printername);
700 DEBUG(10,("connecting to: %s as %s for %s and access: %x\n",
701 pipe_hnd->srv_name_slash, username, printername2, access_required));
703 /* open printer */
704 result = rpccli_spoolss_openprinter_ex(pipe_hnd, mem_ctx,
705 printername2,
706 access_required,
707 hnd);
709 /* be more verbose */
710 if (W_ERROR_V(result) == W_ERROR_V(WERR_ACCESS_DENIED)) {
711 d_fprintf(stderr,
712 _("no access to printer [%s] on [%s] for user [%s] "
713 "granted\n"),
714 printername2, pipe_hnd->srv_name_slash, username);
715 return false;
718 if (!W_ERROR_IS_OK(result)) {
719 d_fprintf(stderr,_("cannot open printer %s on server %s: %s\n"),
720 printername2, pipe_hnd->srv_name_slash, win_errstr(result));
721 return false;
724 DEBUG(2,("got printer handle for printer: %s, server: %s\n",
725 printername2, pipe_hnd->srv_name_slash));
727 return true;
730 static bool net_spoolss_getprinter(struct rpc_pipe_client *pipe_hnd,
731 TALLOC_CTX *mem_ctx,
732 struct policy_handle *hnd,
733 uint32_t level,
734 union spoolss_PrinterInfo *info)
736 WERROR result;
738 /* getprinter call */
739 result = rpccli_spoolss_getprinter(pipe_hnd, mem_ctx,
740 hnd,
741 level,
742 0, /* offered */
743 info);
744 if (!W_ERROR_IS_OK(result)) {
745 printf(_("cannot get printer-info: %s\n"), win_errstr(result));
746 return false;
749 return true;
752 static bool net_spoolss_setprinter(struct rpc_pipe_client *pipe_hnd,
753 TALLOC_CTX *mem_ctx,
754 struct policy_handle *hnd,
755 uint32_t level,
756 union spoolss_PrinterInfo *info)
758 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
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 = dcerpc_spoolss_SetPrinter(b, mem_ctx,
820 hnd,
821 &info_ctr,
822 &devmode_ctr,
823 &secdesc_ctr,
824 0, /* command */
825 &result);
826 if (!NT_STATUS_IS_OK(status)) {
827 printf(_("cannot set printer-info: %s\n"), nt_errstr(status));
828 return false;
830 if (!W_ERROR_IS_OK(result)) {
831 printf(_("cannot set printer-info: %s\n"), win_errstr(result));
832 return false;
835 return true;
839 static bool net_spoolss_setprinterdata(struct rpc_pipe_client *pipe_hnd,
840 TALLOC_CTX *mem_ctx,
841 struct policy_handle *hnd,
842 const char *value_name,
843 enum winreg_Type type,
844 uint8_t *data,
845 uint32_t offered)
847 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
848 WERROR result;
849 NTSTATUS status;
851 /* setprinterdata call */
852 status = dcerpc_spoolss_SetPrinterData(b, mem_ctx,
853 hnd,
854 value_name,
855 type,
856 data,
857 offered,
858 &result);
859 if (!NT_STATUS_IS_OK(status)) {
860 printf (_("unable to set printerdata: %s\n"),
861 nt_errstr(status));
862 return false;
864 if (!W_ERROR_IS_OK(result)) {
865 printf (_("unable to set printerdata: %s\n"),
866 win_errstr(result));
867 return false;
870 return true;
874 static bool net_spoolss_enumprinterkey(struct rpc_pipe_client *pipe_hnd,
875 TALLOC_CTX *mem_ctx,
876 struct policy_handle *hnd,
877 const char *keyname,
878 const char ***keylist)
880 WERROR result;
882 /* enumprinterkey call */
883 result = rpccli_spoolss_enumprinterkey(pipe_hnd, mem_ctx, hnd, keyname, keylist, 0);
885 if (!W_ERROR_IS_OK(result)) {
886 printf(_("enumprinterkey failed: %s\n"), win_errstr(result));
887 return false;
890 return true;
893 static bool net_spoolss_enumprinterdataex(struct rpc_pipe_client *pipe_hnd,
894 TALLOC_CTX *mem_ctx,
895 uint32_t offered,
896 struct policy_handle *hnd,
897 const char *keyname,
898 uint32_t *count,
899 struct spoolss_PrinterEnumValues **info)
901 WERROR result;
903 /* enumprinterdataex call */
904 result = rpccli_spoolss_enumprinterdataex(pipe_hnd, mem_ctx,
905 hnd,
906 keyname,
907 0, /* offered */
908 count,
909 info);
911 if (!W_ERROR_IS_OK(result)) {
912 printf(_("enumprinterdataex failed: %s\n"), win_errstr(result));
913 return false;
916 return true;
920 static bool net_spoolss_setprinterdataex(struct rpc_pipe_client *pipe_hnd,
921 TALLOC_CTX *mem_ctx,
922 struct policy_handle *hnd,
923 const char *keyname,
924 struct regval_blob *value)
926 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
927 WERROR result;
928 NTSTATUS status;
930 /* setprinterdataex call */
931 status = dcerpc_spoolss_SetPrinterDataEx(b, mem_ctx,
932 hnd,
933 keyname,
934 regval_name(value),
935 regval_type(value),
936 regval_data_p(value),
937 regval_size(value),
938 &result);
939 if (!NT_STATUS_IS_OK(status)) {
940 printf(_("could not set printerdataex: %s\n"),
941 nt_errstr(status));
942 return false;
944 if (!W_ERROR_IS_OK(result)) {
945 printf(_("could not set printerdataex: %s\n"),
946 win_errstr(result));
947 return false;
950 return true;
953 static bool net_spoolss_enumforms(struct rpc_pipe_client *pipe_hnd,
954 TALLOC_CTX *mem_ctx,
955 struct policy_handle *hnd,
956 int level,
957 uint32_t *num_forms,
958 union spoolss_FormInfo **forms)
960 WERROR result;
962 /* enumforms call */
963 result = rpccli_spoolss_enumforms(pipe_hnd, mem_ctx,
964 hnd,
965 level,
967 num_forms,
968 forms);
969 if (!W_ERROR_IS_OK(result)) {
970 printf(_("could not enum forms: %s\n"), win_errstr(result));
971 return false;
974 return true;
977 static bool net_spoolss_enumprinterdrivers (struct rpc_pipe_client *pipe_hnd,
978 TALLOC_CTX *mem_ctx,
979 uint32_t level, const char *env,
980 uint32_t *count,
981 union spoolss_DriverInfo **info)
983 WERROR result;
985 /* enumprinterdrivers call */
986 result = rpccli_spoolss_enumprinterdrivers(pipe_hnd, mem_ctx,
987 pipe_hnd->srv_name_slash,
988 env,
989 level,
991 count,
992 info);
993 if (!W_ERROR_IS_OK(result)) {
994 if (W_ERROR_V(result) != W_ERROR_V(WERR_INVALID_ENVIRONMENT)) {
995 printf(_("cannot enum drivers for environment %s: %s\n"), env,
996 win_errstr(result));
997 return false;
998 } else {
999 printf(_("Server does not support environment [%s]\n"),
1000 env);
1004 return true;
1007 static bool net_spoolss_getprinterdriver(struct rpc_pipe_client *pipe_hnd,
1008 TALLOC_CTX *mem_ctx,
1009 struct policy_handle *hnd, uint32_t level,
1010 const char *env, int version,
1011 union spoolss_DriverInfo *info)
1013 WERROR result;
1014 uint32_t server_major_version;
1015 uint32_t server_minor_version;
1017 /* getprinterdriver call */
1018 result = rpccli_spoolss_getprinterdriver2(pipe_hnd, mem_ctx,
1019 hnd,
1020 env,
1021 level,
1023 version,
1025 info,
1026 &server_major_version,
1027 &server_minor_version);
1028 if (!W_ERROR_IS_OK(result)) {
1029 DEBUG(1,("cannot get driver (for architecture: %s): %s\n",
1030 env, win_errstr(result)));
1031 if (W_ERROR_V(result) != W_ERROR_V(WERR_UNKNOWN_PRINTER_DRIVER) &&
1032 W_ERROR_V(result) != W_ERROR_V(WERR_INVALID_ENVIRONMENT)) {
1033 printf(_("cannot get driver: %s\n"),
1034 win_errstr(result));
1036 return false;
1039 return true;
1043 static bool net_spoolss_addprinterdriver(struct rpc_pipe_client *pipe_hnd,
1044 TALLOC_CTX *mem_ctx, uint32_t level,
1045 union spoolss_DriverInfo *info)
1047 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
1048 WERROR result;
1049 NTSTATUS status;
1050 struct spoolss_AddDriverInfoCtr info_ctr;
1052 info_ctr.level = level;
1054 switch (level) {
1055 case 2:
1056 info_ctr.info.info2 = (struct spoolss_AddDriverInfo2 *)
1057 (void *)&info->info2;
1058 break;
1059 case 3:
1060 info_ctr.info.info3 = (struct spoolss_AddDriverInfo3 *)
1061 (void *)&info->info3;
1062 break;
1063 default:
1064 printf(_("unsupported info level: %d\n"), level);
1065 return false;
1068 /* addprinterdriver call */
1069 status = dcerpc_spoolss_AddPrinterDriver(b, mem_ctx,
1070 pipe_hnd->srv_name_slash,
1071 &info_ctr,
1072 &result);
1073 if (!NT_STATUS_IS_OK(status)) {
1074 printf(_("cannot add driver: %s\n"), nt_errstr(status));
1075 return false;
1077 /* be more verbose */
1078 if (W_ERROR_V(result) == W_ERROR_V(WERR_ACCESS_DENIED)) {
1079 printf(_("You are not allowed to add drivers\n"));
1080 return false;
1082 if (!W_ERROR_IS_OK(result)) {
1083 printf(_("cannot add driver: %s\n"), win_errstr(result));
1084 return false;
1087 return true;
1091 * abstraction function to get uint32_t num_printers and PRINTER_INFO_CTR ctr
1092 * for a single printer or for all printers depending on argc/argv
1095 static bool get_printer_info(struct rpc_pipe_client *pipe_hnd,
1096 TALLOC_CTX *mem_ctx,
1097 int level,
1098 int argc,
1099 const char **argv,
1100 uint32_t *num_printers,
1101 union spoolss_PrinterInfo **info_p)
1103 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
1104 struct policy_handle hnd;
1105 WERROR werr;
1107 /* no arguments given, enumerate all printers */
1108 if (argc == 0) {
1110 if (!net_spoolss_enum_printers(pipe_hnd, mem_ctx, NULL,
1111 PRINTER_ENUM_LOCAL|PRINTER_ENUM_SHARED,
1112 level, num_printers, info_p))
1113 return false;
1115 goto out;
1118 /* argument given, get a single printer by name */
1119 if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, argv[0],
1120 MAXIMUM_ALLOWED_ACCESS,
1121 pipe_hnd->auth->user_name,
1122 &hnd))
1123 return false;
1125 *info_p = talloc_zero(mem_ctx, union spoolss_PrinterInfo);
1126 if (*info_p == NULL) {
1127 return false;
1130 if (!net_spoolss_getprinter(pipe_hnd, mem_ctx, &hnd, level, *info_p)) {
1131 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &werr);
1132 return false;
1135 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &werr);
1137 *num_printers = 1;
1139 out:
1140 DEBUG(3,("got %d printers\n", *num_printers));
1142 return true;
1147 * List print-queues (including local printers that are not shared)
1149 * All parameters are provided by the run_rpc_command function, except for
1150 * argc, argv which are passed through.
1152 * @param c A net_context structure
1153 * @param domain_sid The domain sid aquired from the remote server
1154 * @param cli A cli_state connected to the server.
1155 * @param mem_ctx Talloc context, destoyed on compleation of the function.
1156 * @param argc Standard main() style argc
1157 * @param argv Standard main() style argv. Initial components are already
1158 * stripped
1160 * @return Normal NTSTATUS return.
1163 NTSTATUS rpc_printer_list_internals(struct net_context *c,
1164 const struct dom_sid *domain_sid,
1165 const char *domain_name,
1166 struct cli_state *cli,
1167 struct rpc_pipe_client *pipe_hnd,
1168 TALLOC_CTX *mem_ctx,
1169 int argc,
1170 const char **argv)
1172 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1173 uint32_t i, num_printers;
1174 uint32_t level = 2;
1175 const char *printername, *sharename;
1176 union spoolss_PrinterInfo *info;
1178 printf("listing printers\n");
1180 if (!get_printer_info(pipe_hnd, mem_ctx, level, argc, argv, &num_printers, &info))
1181 return nt_status;
1183 for (i = 0; i < num_printers; i++) {
1185 /* do some initialization */
1186 printername = info[i].info2.printername;
1187 sharename = info[i].info2.sharename;
1189 if (printername && sharename) {
1190 d_printf(_("printer %d: %s, shared as: %s\n"),
1191 i+1, printername, sharename);
1195 return NT_STATUS_OK;
1199 * List printer-drivers from a server
1201 * All parameters are provided by the run_rpc_command function, except for
1202 * argc, argv which are passed through.
1204 * @param c A net_context structure
1205 * @param domain_sid The domain sid aquired from the remote server
1206 * @param cli A cli_state connected to the server.
1207 * @param mem_ctx Talloc context, destoyed on compleation of the function.
1208 * @param argc Standard main() style argc
1209 * @param argv Standard main() style argv. Initial components are already
1210 * stripped
1212 * @return Normal NTSTATUS return.
1215 NTSTATUS rpc_printer_driver_list_internals(struct net_context *c,
1216 const struct dom_sid *domain_sid,
1217 const char *domain_name,
1218 struct cli_state *cli,
1219 struct rpc_pipe_client *pipe_hnd,
1220 TALLOC_CTX *mem_ctx,
1221 int argc,
1222 const char **argv)
1224 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1225 uint32_t i;
1226 uint32_t level = 3;
1227 union spoolss_DriverInfo *info;
1228 int d;
1230 printf(_("listing printer-drivers\n"));
1232 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1234 uint32_t num_drivers;
1236 /* enum remote drivers */
1237 if (!net_spoolss_enumprinterdrivers(pipe_hnd, mem_ctx, level,
1238 archi_table[i].long_archi,
1239 &num_drivers, &info)) {
1240 nt_status = NT_STATUS_UNSUCCESSFUL;
1241 goto done;
1244 if (num_drivers == 0) {
1245 d_printf(_("no drivers found on server for "
1246 "architecture: [%s].\n"),
1247 archi_table[i].long_archi);
1248 continue;
1251 d_printf(_("got %d printer-drivers for architecture: [%s]\n"),
1252 num_drivers, archi_table[i].long_archi);
1255 /* do something for all drivers for architecture */
1256 for (d = 0; d < num_drivers; d++) {
1257 display_print_driver3(&info[d].info3);
1261 nt_status = NT_STATUS_OK;
1263 done:
1264 return nt_status;
1269 * Publish print-queues with args-wrapper
1271 * @param cli A cli_state connected to the server.
1272 * @param mem_ctx Talloc context, destoyed on compleation of the function.
1273 * @param argc Standard main() style argc
1274 * @param argv Standard main() style argv. Initial components are already
1275 * stripped
1276 * @param action
1278 * @return Normal NTSTATUS return.
1281 static NTSTATUS rpc_printer_publish_internals_args(struct rpc_pipe_client *pipe_hnd,
1282 TALLOC_CTX *mem_ctx,
1283 int argc,
1284 const char **argv,
1285 uint32_t action)
1287 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
1288 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1289 uint32_t i, num_printers;
1290 uint32_t level = 7;
1291 const char *printername, *sharename;
1292 union spoolss_PrinterInfo *info_enum;
1293 union spoolss_PrinterInfo info;
1294 struct spoolss_SetPrinterInfoCtr info_ctr;
1295 struct spoolss_DevmodeContainer devmode_ctr;
1296 struct sec_desc_buf secdesc_ctr;
1297 struct policy_handle hnd;
1298 WERROR result;
1299 const char *action_str;
1301 if (!get_printer_info(pipe_hnd, mem_ctx, 2, argc, argv, &num_printers, &info_enum))
1302 return nt_status;
1304 for (i = 0; i < num_printers; i++) {
1306 /* do some initialization */
1307 printername = info_enum[i].info2.printername;
1308 sharename = info_enum[i].info2.sharename;
1309 if (!printername || !sharename) {
1310 goto done;
1313 /* open printer handle */
1314 if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, sharename,
1315 PRINTER_ALL_ACCESS, pipe_hnd->auth->user_name, &hnd))
1316 goto done;
1318 /* check for existing dst printer */
1319 if (!net_spoolss_getprinter(pipe_hnd, mem_ctx, &hnd, level, &info))
1320 goto done;
1322 /* check action and set string */
1323 switch (action) {
1324 case DSPRINT_PUBLISH:
1325 action_str = N_("published");
1326 break;
1327 case DSPRINT_UPDATE:
1328 action_str = N_("updated");
1329 break;
1330 case DSPRINT_UNPUBLISH:
1331 action_str = N_("unpublished");
1332 break;
1333 default:
1334 action_str = N_("unknown action");
1335 printf(_("unknown action: %d\n"), action);
1336 break;
1339 info.info7.action = action;
1340 info_ctr.level = 7;
1341 info_ctr.info.info7 = (struct spoolss_SetPrinterInfo7 *)
1342 (void *)&info.info7;
1344 ZERO_STRUCT(devmode_ctr);
1345 ZERO_STRUCT(secdesc_ctr);
1347 nt_status = dcerpc_spoolss_SetPrinter(b, mem_ctx,
1348 &hnd,
1349 &info_ctr,
1350 &devmode_ctr,
1351 &secdesc_ctr,
1352 0, /* command */
1353 &result);
1354 if (!NT_STATUS_IS_OK(nt_status)) {
1355 printf(_("cannot set printer-info: %s\n"),
1356 nt_errstr(nt_status));
1357 goto done;
1359 if (!W_ERROR_IS_OK(result) && !W_ERROR_EQUAL(result, WERR_IO_PENDING)) {
1360 if ((action == DSPRINT_UPDATE) && W_ERROR_EQUAL(result, W_ERROR(0x80070002))) {
1361 printf(_("printer not published yet\n"));
1362 } else {
1363 printf(_("cannot set printer-info: %s\n"),
1364 win_errstr(result));
1366 nt_status = werror_to_ntstatus(result);
1367 goto done;
1370 printf(_("successfully %s printer %s in Active Directory\n"),
1371 action_str, sharename);
1374 nt_status = NT_STATUS_OK;
1376 done:
1377 if (is_valid_policy_hnd(&hnd)) {
1378 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &result);
1381 return nt_status;
1384 NTSTATUS rpc_printer_publish_publish_internals(struct net_context *c,
1385 const struct dom_sid *domain_sid,
1386 const char *domain_name,
1387 struct cli_state *cli,
1388 struct rpc_pipe_client *pipe_hnd,
1389 TALLOC_CTX *mem_ctx,
1390 int argc,
1391 const char **argv)
1393 return rpc_printer_publish_internals_args(pipe_hnd, mem_ctx, argc, argv, DSPRINT_PUBLISH);
1396 NTSTATUS rpc_printer_publish_unpublish_internals(struct net_context *c,
1397 const struct dom_sid *domain_sid,
1398 const char *domain_name,
1399 struct cli_state *cli,
1400 struct rpc_pipe_client *pipe_hnd,
1401 TALLOC_CTX *mem_ctx,
1402 int argc,
1403 const char **argv)
1405 return rpc_printer_publish_internals_args(pipe_hnd, mem_ctx, argc, argv, DSPRINT_UNPUBLISH);
1408 NTSTATUS rpc_printer_publish_update_internals(struct net_context *c,
1409 const struct dom_sid *domain_sid,
1410 const char *domain_name,
1411 struct cli_state *cli,
1412 struct rpc_pipe_client *pipe_hnd,
1413 TALLOC_CTX *mem_ctx,
1414 int argc,
1415 const char **argv)
1417 return rpc_printer_publish_internals_args(pipe_hnd, mem_ctx, argc, argv, DSPRINT_UPDATE);
1421 * List print-queues w.r.t. their publishing state
1423 * All parameters are provided by the run_rpc_command function, except for
1424 * argc, argv which are passed through.
1426 * @param c A net_context structure
1427 * @param domain_sid The domain sid aquired from the remote server
1428 * @param cli A cli_state connected to the server.
1429 * @param mem_ctx Talloc context, destoyed on compleation of the function.
1430 * @param argc Standard main() style argc
1431 * @param argv Standard main() style argv. Initial components are already
1432 * stripped
1434 * @return Normal NTSTATUS return.
1437 NTSTATUS rpc_printer_publish_list_internals(struct net_context *c,
1438 const struct dom_sid *domain_sid,
1439 const char *domain_name,
1440 struct cli_state *cli,
1441 struct rpc_pipe_client *pipe_hnd,
1442 TALLOC_CTX *mem_ctx,
1443 int argc,
1444 const char **argv)
1446 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
1447 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1448 uint32_t i, num_printers;
1449 uint32_t level = 7;
1450 const char *printername, *sharename;
1451 union spoolss_PrinterInfo *info_enum;
1452 union spoolss_PrinterInfo info;
1453 struct policy_handle hnd;
1454 int state;
1455 WERROR werr;
1457 if (!get_printer_info(pipe_hnd, mem_ctx, 2, argc, argv, &num_printers, &info_enum))
1458 return nt_status;
1460 for (i = 0; i < num_printers; i++) {
1462 /* do some initialization */
1463 printername = info_enum[i].info2.printername;
1464 sharename = info_enum[i].info2.sharename;
1466 if (!printername || !sharename) {
1467 goto done;
1470 /* open printer handle */
1471 if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, sharename,
1472 PRINTER_ALL_ACCESS, cli->user_name, &hnd))
1473 goto done;
1475 /* check for existing dst printer */
1476 if (!net_spoolss_getprinter(pipe_hnd, mem_ctx, &hnd, level, &info))
1477 goto done;
1479 if (!info.info7.guid) {
1480 goto done;
1482 state = info.info7.action;
1483 switch (state) {
1484 case DSPRINT_PUBLISH:
1485 printf(_("printer [%s] is published"),
1486 sharename);
1487 if (c->opt_verbose)
1488 printf(_(", guid: %s"),info.info7.guid);
1489 printf("\n");
1490 break;
1491 case DSPRINT_UNPUBLISH:
1492 printf(_("printer [%s] is unpublished\n"),
1493 sharename);
1494 break;
1495 case DSPRINT_UPDATE:
1496 printf(_("printer [%s] is currently updating\n"),
1497 sharename);
1498 break;
1499 default:
1500 printf(_("unknown state: %d\n"), state);
1501 break;
1505 nt_status = NT_STATUS_OK;
1507 done:
1508 if (is_valid_policy_hnd(&hnd)) {
1509 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &werr);
1512 return nt_status;
1516 * Migrate Printer-ACLs from a source server to the destination server
1518 * All parameters are provided by the run_rpc_command function, except for
1519 * argc, argv which are passed through.
1521 * @param c A net_context structure
1522 * @param domain_sid The domain sid aquired from the remote server
1523 * @param cli A cli_state connected to the server.
1524 * @param mem_ctx Talloc context, destoyed on compleation of the function.
1525 * @param argc Standard main() style argc
1526 * @param argv Standard main() style argv. Initial components are already
1527 * stripped
1529 * @return Normal NTSTATUS return.
1532 NTSTATUS rpc_printer_migrate_security_internals(struct net_context *c,
1533 const struct dom_sid *domain_sid,
1534 const char *domain_name,
1535 struct cli_state *cli,
1536 struct rpc_pipe_client *pipe_hnd,
1537 TALLOC_CTX *mem_ctx,
1538 int argc,
1539 const char **argv)
1541 struct dcerpc_binding_handle *b_src = pipe_hnd->binding_handle;
1542 /* TODO: what now, info2 or info3 ?
1543 convince jerry that we should add clientside setacls level 3 at least
1545 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1546 uint32_t i = 0;
1547 uint32_t num_printers;
1548 uint32_t level = 2;
1549 const char *printername, *sharename;
1550 struct rpc_pipe_client *pipe_hnd_dst = NULL;
1551 struct dcerpc_binding_handle *b_dst = NULL;
1552 struct policy_handle hnd_src, hnd_dst;
1553 union spoolss_PrinterInfo *info_enum;
1554 struct cli_state *cli_dst = NULL;
1555 union spoolss_PrinterInfo info_src, info_dst;
1556 WERROR werr;
1558 DEBUG(3,("copying printer ACLs\n"));
1560 /* connect destination PI_SPOOLSS */
1561 nt_status = connect_dst_pipe(c, &cli_dst, &pipe_hnd_dst,
1562 &ndr_table_spoolss.syntax_id);
1563 if (!NT_STATUS_IS_OK(nt_status)) {
1564 return nt_status;
1566 b_dst = pipe_hnd_dst->binding_handle;
1568 /* enum source printers */
1569 if (!get_printer_info(pipe_hnd, mem_ctx, level, argc, argv, &num_printers, &info_enum)) {
1570 nt_status = NT_STATUS_UNSUCCESSFUL;
1571 goto done;
1574 if (!num_printers) {
1575 printf (_("no printers found on server.\n"));
1576 nt_status = NT_STATUS_OK;
1577 goto done;
1580 /* do something for all printers */
1581 for (i = 0; i < num_printers; i++) {
1583 /* do some initialization */
1584 printername = info_enum[i].info2.printername;
1585 sharename = info_enum[i].info2.sharename;
1587 if (!printername || !sharename) {
1588 nt_status = NT_STATUS_UNSUCCESSFUL;
1589 goto done;
1592 /* we can reset NT_STATUS here because we do not
1593 get any real NT_STATUS-codes anymore from now on */
1594 nt_status = NT_STATUS_UNSUCCESSFUL;
1596 d_printf(_("migrating printer ACLs for: [%s] / [%s]\n"),
1597 printername, sharename);
1599 /* according to msdn you have specify these access-rights
1600 to see the security descriptor
1601 - READ_CONTROL (DACL)
1602 - ACCESS_SYSTEM_SECURITY (SACL)
1605 /* open src printer handle */
1606 if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, sharename,
1607 MAXIMUM_ALLOWED_ACCESS, cli->user_name, &hnd_src))
1608 goto done;
1610 /* open dst printer handle */
1611 if (!net_spoolss_open_printer_ex(pipe_hnd_dst, mem_ctx, sharename,
1612 PRINTER_ALL_ACCESS, cli_dst->user_name, &hnd_dst))
1613 goto done;
1615 /* check for existing dst printer */
1616 if (!net_spoolss_getprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, level, &info_dst))
1617 goto done;
1619 /* check for existing src printer */
1620 if (!net_spoolss_getprinter(pipe_hnd, mem_ctx, &hnd_src, 3, &info_src))
1621 goto done;
1623 /* Copy Security Descriptor */
1625 /* copy secdesc (info level 2) */
1626 info_dst.info2.devmode = NULL;
1627 info_dst.info2.secdesc = dup_sec_desc(mem_ctx, info_src.info3.secdesc);
1629 if (c->opt_verbose)
1630 display_sec_desc(info_dst.info2.secdesc);
1632 if (!net_spoolss_setprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, 2, &info_dst))
1633 goto done;
1635 DEBUGADD(1,("\tSetPrinter of SECDESC succeeded\n"));
1638 /* close printer handles here */
1639 if (is_valid_policy_hnd(&hnd_src)) {
1640 dcerpc_spoolss_ClosePrinter(b_src, mem_ctx, &hnd_src, &werr);
1643 if (is_valid_policy_hnd(&hnd_dst)) {
1644 dcerpc_spoolss_ClosePrinter(b_dst, mem_ctx, &hnd_dst, &werr);
1649 nt_status = NT_STATUS_OK;
1651 done:
1653 if (is_valid_policy_hnd(&hnd_src)) {
1654 dcerpc_spoolss_ClosePrinter(b_src, mem_ctx, &hnd_src, &werr);
1657 if (is_valid_policy_hnd(&hnd_dst)) {
1658 dcerpc_spoolss_ClosePrinter(b_dst, mem_ctx, &hnd_dst, &werr);
1661 if (cli_dst) {
1662 cli_shutdown(cli_dst);
1664 return nt_status;
1668 * Migrate printer-forms from a src server to the dst server
1670 * All parameters are provided by the run_rpc_command function, except for
1671 * argc, argv which are passed through.
1673 * @param c A net_context structure
1674 * @param domain_sid The domain sid aquired from the remote server
1675 * @param cli A cli_state connected to the server.
1676 * @param mem_ctx Talloc context, destoyed on compleation of the function.
1677 * @param argc Standard main() style argc
1678 * @param argv Standard main() style argv. Initial components are already
1679 * stripped
1681 * @return Normal NTSTATUS return.
1684 NTSTATUS rpc_printer_migrate_forms_internals(struct net_context *c,
1685 const struct dom_sid *domain_sid,
1686 const char *domain_name,
1687 struct cli_state *cli,
1688 struct rpc_pipe_client *pipe_hnd,
1689 TALLOC_CTX *mem_ctx,
1690 int argc,
1691 const char **argv)
1693 struct dcerpc_binding_handle *b_src = pipe_hnd->binding_handle;
1694 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1695 WERROR result;
1696 uint32_t i, f;
1697 uint32_t num_printers;
1698 uint32_t level = 1;
1699 const char *printername, *sharename;
1700 struct rpc_pipe_client *pipe_hnd_dst = NULL;
1701 struct dcerpc_binding_handle *b_dst = NULL;
1702 struct policy_handle hnd_src, hnd_dst;
1703 union spoolss_PrinterInfo *info_enum;
1704 union spoolss_PrinterInfo info_dst;
1705 uint32_t num_forms;
1706 union spoolss_FormInfo *forms;
1707 struct cli_state *cli_dst = NULL;
1709 DEBUG(3,("copying forms\n"));
1711 /* connect destination PI_SPOOLSS */
1712 nt_status = connect_dst_pipe(c, &cli_dst, &pipe_hnd_dst,
1713 &ndr_table_spoolss.syntax_id);
1714 if (!NT_STATUS_IS_OK(nt_status)) {
1715 return nt_status;
1717 b_dst = pipe_hnd_dst->binding_handle;
1719 /* enum src printers */
1720 if (!get_printer_info(pipe_hnd, mem_ctx, 2, argc, argv, &num_printers, &info_enum)) {
1721 nt_status = NT_STATUS_UNSUCCESSFUL;
1722 goto done;
1725 if (!num_printers) {
1726 printf (_("no printers found on server.\n"));
1727 nt_status = NT_STATUS_OK;
1728 goto done;
1731 /* do something for all printers */
1732 for (i = 0; i < num_printers; i++) {
1734 /* do some initialization */
1735 printername = info_enum[i].info2.printername;
1736 sharename = info_enum[i].info2.sharename;
1738 if (!printername || !sharename) {
1739 nt_status = NT_STATUS_UNSUCCESSFUL;
1740 goto done;
1742 /* we can reset NT_STATUS here because we do not
1743 get any real NT_STATUS-codes anymore from now on */
1744 nt_status = NT_STATUS_UNSUCCESSFUL;
1746 d_printf(_("migrating printer forms for: [%s] / [%s]\n"),
1747 printername, sharename);
1750 /* open src printer handle */
1751 if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, sharename,
1752 MAXIMUM_ALLOWED_ACCESS, cli->user_name, &hnd_src))
1753 goto done;
1755 /* open dst printer handle */
1756 if (!net_spoolss_open_printer_ex(pipe_hnd_dst, mem_ctx, sharename,
1757 PRINTER_ALL_ACCESS, cli->user_name, &hnd_dst))
1758 goto done;
1760 /* check for existing dst printer */
1761 if (!net_spoolss_getprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, level, &info_dst))
1762 goto done;
1764 /* finally migrate forms */
1765 if (!net_spoolss_enumforms(pipe_hnd, mem_ctx, &hnd_src, level, &num_forms, &forms))
1766 goto done;
1768 DEBUG(1,("got %d forms for printer\n", num_forms));
1771 for (f = 0; f < num_forms; f++) {
1773 union spoolss_AddFormInfo info;
1774 NTSTATUS status;
1776 /* only migrate FORM_PRINTER types, according to jerry
1777 FORM_BUILTIN-types are hard-coded in samba */
1778 if (forms[f].info1.flags != SPOOLSS_FORM_PRINTER)
1779 continue;
1781 if (c->opt_verbose)
1782 d_printf(_("\tmigrating form # %d [%s] of type "
1783 "[%d]\n"),
1784 f, forms[f].info1.form_name,
1785 forms[f].info1.flags);
1787 info.info1 = (struct spoolss_AddFormInfo1 *)
1788 (void *)&forms[f].info1;
1790 /* FIXME: there might be something wrong with samba's
1791 builtin-forms */
1792 status = dcerpc_spoolss_AddForm(b_dst, mem_ctx,
1793 &hnd_dst,
1795 info,
1796 &result);
1797 if (!NT_STATUS_IS_OK(status)) {
1798 d_printf(_("\tdcerpc_spoolss_AddForm form %d: [%s] - %s\n"),
1799 f, forms[f].info1.form_name, nt_errstr(status));
1800 continue;
1802 if (!W_ERROR_IS_OK(result)) {
1803 d_printf(_("\tAddForm form %d: [%s] refused.\n"),
1804 f, forms[f].info1.form_name);
1805 continue;
1808 DEBUGADD(1,("\tAddForm of [%s] succeeded\n",
1809 forms[f].info1.form_name));
1813 /* close printer handles here */
1814 if (is_valid_policy_hnd(&hnd_src)) {
1815 dcerpc_spoolss_ClosePrinter(b_src, mem_ctx, &hnd_src, &result);
1818 if (is_valid_policy_hnd(&hnd_dst)) {
1819 dcerpc_spoolss_ClosePrinter(b_dst, mem_ctx, &hnd_dst, &result);
1823 nt_status = NT_STATUS_OK;
1825 done:
1827 if (is_valid_policy_hnd(&hnd_src)) {
1828 dcerpc_spoolss_ClosePrinter(b_src, mem_ctx, &hnd_src, &result);
1831 if (is_valid_policy_hnd(&hnd_dst)) {
1832 dcerpc_spoolss_ClosePrinter(b_dst, mem_ctx, &hnd_dst, &result);
1835 if (cli_dst) {
1836 cli_shutdown(cli_dst);
1838 return nt_status;
1842 * Migrate printer-drivers from a src server to the dst server
1844 * All parameters are provided by the run_rpc_command function, except for
1845 * argc, argv which are passed through.
1847 * @param c A net_context structure
1848 * @param domain_sid The domain sid aquired from the remote server
1849 * @param cli A cli_state connected to the server.
1850 * @param mem_ctx Talloc context, destoyed on compleation of the function.
1851 * @param argc Standard main() style argc
1852 * @param argv Standard main() style argv. Initial components are already
1853 * stripped
1855 * @return Normal NTSTATUS return.
1858 NTSTATUS rpc_printer_migrate_drivers_internals(struct net_context *c,
1859 const struct dom_sid *domain_sid,
1860 const char *domain_name,
1861 struct cli_state *cli,
1862 struct rpc_pipe_client *pipe_hnd,
1863 TALLOC_CTX *mem_ctx,
1864 int argc,
1865 const char **argv)
1867 struct dcerpc_binding_handle *b_src = pipe_hnd->binding_handle;
1868 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1869 uint32_t i, p;
1870 uint32_t num_printers;
1871 uint32_t level = 3;
1872 const char *printername, *sharename;
1873 bool got_src_driver_share = false;
1874 bool got_dst_driver_share = false;
1875 struct rpc_pipe_client *pipe_hnd_dst = NULL;
1876 struct dcerpc_binding_handle *b_dst = NULL;
1877 struct policy_handle hnd_src, hnd_dst;
1878 union spoolss_DriverInfo drv_info_src;
1879 union spoolss_PrinterInfo *info_enum;
1880 union spoolss_PrinterInfo info_dst;
1881 struct cli_state *cli_dst = NULL;
1882 struct cli_state *cli_share_src = NULL;
1883 struct cli_state *cli_share_dst = NULL;
1884 const char *drivername = NULL;
1885 WERROR werr;
1887 DEBUG(3,("copying printer-drivers\n"));
1889 nt_status = connect_dst_pipe(c, &cli_dst, &pipe_hnd_dst,
1890 &ndr_table_spoolss.syntax_id);
1891 if (!NT_STATUS_IS_OK(nt_status)) {
1892 return nt_status;
1894 b_dst = pipe_hnd_dst->binding_handle;
1896 /* open print$-share on the src server */
1897 nt_status = connect_to_service(c, &cli_share_src, &cli->dest_ss,
1898 cli->desthost, "print$", "A:");
1899 if (!NT_STATUS_IS_OK(nt_status))
1900 goto done;
1902 got_src_driver_share = true;
1905 /* open print$-share on the dst server */
1906 nt_status = connect_to_service(c, &cli_share_dst, &cli_dst->dest_ss,
1907 cli_dst->desthost, "print$", "A:");
1908 if (!NT_STATUS_IS_OK(nt_status))
1909 return nt_status;
1911 got_dst_driver_share = true;
1914 /* enum src printers */
1915 if (!get_printer_info(pipe_hnd, mem_ctx, 2, argc, argv, &num_printers, &info_enum)) {
1916 nt_status = NT_STATUS_UNSUCCESSFUL;
1917 goto done;
1920 if (num_printers == 0) {
1921 printf (_("no printers found on server.\n"));
1922 nt_status = NT_STATUS_OK;
1923 goto done;
1927 /* do something for all printers */
1928 for (p = 0; p < num_printers; p++) {
1930 /* do some initialization */
1931 printername = info_enum[p].info2.printername;
1932 sharename = info_enum[p].info2.sharename;
1934 if (!printername || !sharename) {
1935 nt_status = NT_STATUS_UNSUCCESSFUL;
1936 goto done;
1939 /* we can reset NT_STATUS here because we do not
1940 get any real NT_STATUS-codes anymore from now on */
1941 nt_status = NT_STATUS_UNSUCCESSFUL;
1943 d_printf(_("migrating printer driver for: [%s] / [%s]\n"),
1944 printername, sharename);
1946 /* open dst printer handle */
1947 if (!net_spoolss_open_printer_ex(pipe_hnd_dst, mem_ctx, sharename,
1948 PRINTER_ALL_ACCESS, cli->user_name, &hnd_dst))
1949 goto done;
1951 /* check for existing dst printer */
1952 if (!net_spoolss_getprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, 2, &info_dst))
1953 goto done;
1956 /* open src printer handle */
1957 if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, sharename,
1958 MAXIMUM_ALLOWED_ACCESS,
1959 pipe_hnd->auth->user_name,
1960 &hnd_src))
1961 goto done;
1963 /* in a first step call getdriver for each shared printer (per arch)
1964 to get a list of all files that have to be copied */
1966 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1968 /* getdriver src */
1969 if (!net_spoolss_getprinterdriver(pipe_hnd, mem_ctx, &hnd_src,
1970 level, archi_table[i].long_archi,
1971 archi_table[i].version, &drv_info_src))
1972 continue;
1974 drivername = drv_info_src.info3.driver_name;
1976 if (c->opt_verbose)
1977 display_print_driver3(&drv_info_src.info3);
1979 /* check arch dir */
1980 nt_status = check_arch_dir(cli_share_dst, archi_table[i].short_archi);
1981 if (!NT_STATUS_IS_OK(nt_status))
1982 goto done;
1985 /* copy driver-files */
1986 nt_status = copy_print_driver_3(c, mem_ctx, cli_share_src, cli_share_dst,
1987 archi_table[i].short_archi,
1988 &drv_info_src.info3);
1989 if (!NT_STATUS_IS_OK(nt_status))
1990 goto done;
1993 /* adddriver dst */
1994 if (!net_spoolss_addprinterdriver(pipe_hnd_dst, mem_ctx, level, &drv_info_src)) {
1995 nt_status = NT_STATUS_UNSUCCESSFUL;
1996 goto done;
1999 DEBUGADD(1,("Sucessfully added driver [%s] for printer [%s]\n",
2000 drivername, printername));
2004 if (!drivername || strlen(drivername) == 0) {
2005 DEBUGADD(1,("Did not get driver for printer %s\n",
2006 printername));
2007 goto done;
2010 /* setdriver dst */
2011 info_dst.info2.drivername = drivername;
2013 if (!net_spoolss_setprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, 2, &info_dst)) {
2014 nt_status = NT_STATUS_UNSUCCESSFUL;
2015 goto done;
2018 DEBUGADD(1,("Sucessfully set driver %s for printer %s\n",
2019 drivername, printername));
2021 /* close dst */
2022 if (is_valid_policy_hnd(&hnd_dst)) {
2023 dcerpc_spoolss_ClosePrinter(b_dst, mem_ctx, &hnd_dst, &werr);
2026 /* close src */
2027 if (is_valid_policy_hnd(&hnd_src)) {
2028 dcerpc_spoolss_ClosePrinter(b_src, mem_ctx, &hnd_src, &werr);
2032 nt_status = NT_STATUS_OK;
2034 done:
2036 if (is_valid_policy_hnd(&hnd_dst)) {
2037 dcerpc_spoolss_ClosePrinter(b_dst, mem_ctx, &hnd_dst, &werr);
2040 /* close src */
2041 if (is_valid_policy_hnd(&hnd_src)) {
2042 dcerpc_spoolss_ClosePrinter(b_src, mem_ctx, &hnd_src, &werr);
2045 if (cli_dst) {
2046 cli_shutdown(cli_dst);
2049 if (got_src_driver_share)
2050 cli_shutdown(cli_share_src);
2052 if (got_dst_driver_share)
2053 cli_shutdown(cli_share_dst);
2055 return nt_status;
2060 * Migrate printer-queues from a src to the dst server
2061 * (requires a working "addprinter command" to be installed for the local smbd)
2063 * All parameters are provided by the run_rpc_command function, except for
2064 * argc, argv which are passed through.
2066 * @param c A net_context structure
2067 * @param domain_sid The domain sid aquired from the remote server
2068 * @param cli A cli_state connected to the server.
2069 * @param mem_ctx Talloc context, destoyed on compleation of the function.
2070 * @param argc Standard main() style argc
2071 * @param argv Standard main() style argv. Initial components are already
2072 * stripped
2074 * @return Normal NTSTATUS return.
2077 NTSTATUS rpc_printer_migrate_printers_internals(struct net_context *c,
2078 const struct dom_sid *domain_sid,
2079 const char *domain_name,
2080 struct cli_state *cli,
2081 struct rpc_pipe_client *pipe_hnd,
2082 TALLOC_CTX *mem_ctx,
2083 int argc,
2084 const char **argv)
2086 struct dcerpc_binding_handle *b_src = pipe_hnd->binding_handle;
2087 WERROR result;
2088 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
2089 uint32_t i = 0, num_printers;
2090 uint32_t level = 2;
2091 union spoolss_PrinterInfo info_dst, info_src;
2092 union spoolss_PrinterInfo *info_enum;
2093 struct cli_state *cli_dst = NULL;
2094 struct policy_handle hnd_dst, hnd_src;
2095 const char *printername, *sharename;
2096 struct rpc_pipe_client *pipe_hnd_dst = NULL;
2097 struct dcerpc_binding_handle *b_dst = NULL;
2098 struct spoolss_SetPrinterInfoCtr info_ctr;
2100 DEBUG(3,("copying printers\n"));
2102 /* connect destination PI_SPOOLSS */
2103 nt_status = connect_dst_pipe(c, &cli_dst, &pipe_hnd_dst,
2104 &ndr_table_spoolss.syntax_id);
2105 if (!NT_STATUS_IS_OK(nt_status)) {
2106 return nt_status;
2108 b_dst = pipe_hnd_dst->binding_handle;
2110 /* enum printers */
2111 if (!get_printer_info(pipe_hnd, mem_ctx, level, argc, argv, &num_printers, &info_enum)) {
2112 nt_status = NT_STATUS_UNSUCCESSFUL;
2113 goto done;
2116 if (!num_printers) {
2117 printf (_("no printers found on server.\n"));
2118 nt_status = NT_STATUS_OK;
2119 goto done;
2122 /* do something for all printers */
2123 for (i = 0; i < num_printers; i++) {
2125 struct spoolss_SetPrinterInfo2 info2;
2127 /* do some initialization */
2128 printername = info_enum[i].info2.printername;
2129 sharename = info_enum[i].info2.sharename;
2131 if (!printername || !sharename) {
2132 nt_status = NT_STATUS_UNSUCCESSFUL;
2133 goto done;
2135 /* we can reset NT_STATUS here because we do not
2136 get any real NT_STATUS-codes anymore from now on */
2137 nt_status = NT_STATUS_UNSUCCESSFUL;
2139 d_printf(_("migrating printer queue for: [%s] / [%s]\n"),
2140 printername, sharename);
2142 /* open dst printer handle */
2143 if (!net_spoolss_open_printer_ex(pipe_hnd_dst, mem_ctx, sharename,
2144 PRINTER_ALL_ACCESS, cli->user_name, &hnd_dst)) {
2146 DEBUG(1,("could not open printer: %s\n", sharename));
2149 /* check for existing dst printer */
2150 if (!net_spoolss_getprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, level, &info_dst)) {
2151 printf (_("could not get printer, creating printer.\n"));
2152 } else {
2153 DEBUG(1,("printer already exists: %s\n", sharename));
2154 /* close printer handle here - dst only, not got src yet. */
2155 if (is_valid_policy_hnd(&hnd_dst)) {
2156 dcerpc_spoolss_ClosePrinter(b_dst, mem_ctx, &hnd_dst, &result);
2158 continue;
2161 /* now get again src printer ctr via getprinter,
2162 we first need a handle for that */
2164 /* open src printer handle */
2165 if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, sharename,
2166 MAXIMUM_ALLOWED_ACCESS, cli->user_name, &hnd_src))
2167 goto done;
2169 /* getprinter on the src server */
2170 if (!net_spoolss_getprinter(pipe_hnd, mem_ctx, &hnd_src, level, &info_src))
2171 goto done;
2173 /* copy each src printer to a dst printer 1:1,
2174 maybe some values have to be changed though */
2175 d_printf(_("creating printer: %s\n"), printername);
2177 info_ctr.level = level;
2178 spoolss_printerinfo2_to_setprinterinfo2(&info_src.info2, &info2);
2179 info_ctr.info.info2 = &info2;
2181 result = rpccli_spoolss_addprinterex(pipe_hnd_dst,
2182 mem_ctx,
2183 &info_ctr);
2185 if (W_ERROR_IS_OK(result))
2186 d_printf (_("printer [%s] successfully added.\n"),
2187 printername);
2188 else if (W_ERROR_V(result) == W_ERROR_V(WERR_PRINTER_ALREADY_EXISTS))
2189 d_fprintf (stderr, _("printer [%s] already exists.\n"),
2190 printername);
2191 else {
2192 d_fprintf (stderr, _("could not create printer [%s]\n"),
2193 printername);
2194 goto done;
2197 /* close printer handles here */
2198 if (is_valid_policy_hnd(&hnd_src)) {
2199 dcerpc_spoolss_ClosePrinter(b_src, mem_ctx, &hnd_src, &result);
2202 if (is_valid_policy_hnd(&hnd_dst)) {
2203 dcerpc_spoolss_ClosePrinter(b_dst, mem_ctx, &hnd_dst, &result);
2207 nt_status = NT_STATUS_OK;
2209 done:
2210 if (is_valid_policy_hnd(&hnd_src)) {
2211 dcerpc_spoolss_ClosePrinter(b_src, mem_ctx, &hnd_src, &result);
2214 if (is_valid_policy_hnd(&hnd_dst)) {
2215 dcerpc_spoolss_ClosePrinter(b_dst, mem_ctx, &hnd_dst, &result);
2218 if (cli_dst) {
2219 cli_shutdown(cli_dst);
2221 return nt_status;
2225 * Migrate Printer-Settings from a src server to the dst server
2226 * (for this to work, printers and drivers already have to be migrated earlier)
2228 * All parameters are provided by the run_rpc_command function, except for
2229 * argc, argv which are passed through.
2231 * @param c A net_context structure
2232 * @param domain_sid The domain sid aquired from the remote server
2233 * @param cli A cli_state connected to the server.
2234 * @param mem_ctx Talloc context, destoyed on compleation of the function.
2235 * @param argc Standard main() style argc
2236 * @param argv Standard main() style argv. Initial components are already
2237 * stripped
2239 * @return Normal NTSTATUS return.
2242 NTSTATUS rpc_printer_migrate_settings_internals(struct net_context *c,
2243 const struct dom_sid *domain_sid,
2244 const char *domain_name,
2245 struct cli_state *cli,
2246 struct rpc_pipe_client *pipe_hnd,
2247 TALLOC_CTX *mem_ctx,
2248 int argc,
2249 const char **argv)
2251 struct dcerpc_binding_handle *b_src = pipe_hnd->binding_handle;
2253 /* FIXME: Here the nightmare begins */
2255 WERROR result;
2256 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
2257 uint32_t i = 0, j = 0;
2258 uint32_t num_printers;
2259 uint32_t level = 2;
2260 const char *printername, *sharename;
2261 struct rpc_pipe_client *pipe_hnd_dst = NULL;
2262 struct dcerpc_binding_handle *b_dst = NULL;
2263 struct policy_handle hnd_src, hnd_dst;
2264 union spoolss_PrinterInfo *info_enum;
2265 union spoolss_PrinterInfo info_dst_publish;
2266 union spoolss_PrinterInfo info_dst;
2267 struct cli_state *cli_dst = NULL;
2268 char *devicename = NULL, *unc_name = NULL, *url = NULL;
2269 const char *longname;
2270 const char **keylist = NULL;
2272 /* FIXME GD */
2273 ZERO_STRUCT(info_dst_publish);
2275 DEBUG(3,("copying printer settings\n"));
2277 /* connect destination PI_SPOOLSS */
2278 nt_status = connect_dst_pipe(c, &cli_dst, &pipe_hnd_dst,
2279 &ndr_table_spoolss.syntax_id);
2280 if (!NT_STATUS_IS_OK(nt_status)) {
2281 return nt_status;
2283 b_dst = pipe_hnd_dst->binding_handle;
2285 /* enum src printers */
2286 if (!get_printer_info(pipe_hnd, mem_ctx, level, argc, argv, &num_printers, &info_enum)) {
2287 nt_status = NT_STATUS_UNSUCCESSFUL;
2288 goto done;
2291 if (!num_printers) {
2292 printf (_("no printers found on server.\n"));
2293 nt_status = NT_STATUS_OK;
2294 goto done;
2298 /* needed for dns-strings in regkeys */
2299 longname = get_mydnsfullname();
2300 if (!longname) {
2301 nt_status = NT_STATUS_UNSUCCESSFUL;
2302 goto done;
2305 /* do something for all printers */
2306 for (i = 0; i < num_printers; i++) {
2308 uint32_t value_needed;
2309 uint32_t data_needed;
2310 enum winreg_Type type;
2311 struct spoolss_EnumPrinterData r;
2313 /* do some initialization */
2314 printername = info_enum[i].info2.printername;
2315 sharename = info_enum[i].info2.sharename;
2317 if (!printername || !sharename) {
2318 nt_status = NT_STATUS_UNSUCCESSFUL;
2319 goto done;
2321 /* we can reset NT_STATUS here because we do not
2322 get any real NT_STATUS-codes anymore from now on */
2323 nt_status = NT_STATUS_UNSUCCESSFUL;
2325 d_printf(_("migrating printer settings for: [%s] / [%s]\n"),
2326 printername, sharename);
2329 /* open src printer handle */
2330 if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, sharename,
2331 MAXIMUM_ALLOWED_ACCESS, cli->user_name, &hnd_src))
2332 goto done;
2334 /* open dst printer handle */
2335 if (!net_spoolss_open_printer_ex(pipe_hnd_dst, mem_ctx, sharename,
2336 PRINTER_ALL_ACCESS, cli_dst->user_name, &hnd_dst))
2337 goto done;
2339 /* check for existing dst printer */
2340 if (!net_spoolss_getprinter(pipe_hnd_dst, mem_ctx, &hnd_dst,
2341 level, &info_dst))
2342 goto done;
2345 /* STEP 1: COPY DEVICE-MODE and other
2346 PRINTER_INFO_2-attributes
2349 info_dst.info2 = info_enum[i].info2;
2351 /* why is the port always disconnected when the printer
2352 is correctly installed (incl. driver ???) */
2353 info_dst.info2.portname = SAMBA_PRINTER_PORT_NAME;
2355 /* check if printer is published */
2356 if (info_enum[i].info2.attributes & PRINTER_ATTRIBUTE_PUBLISHED) {
2358 /* check for existing dst printer */
2359 if (!net_spoolss_getprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, 7, &info_dst_publish))
2360 goto done;
2362 info_dst_publish.info7.action = DSPRINT_PUBLISH;
2364 /* ignore false from setprinter due to WERR_IO_PENDING */
2365 net_spoolss_setprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, 7, &info_dst_publish);
2367 DEBUG(3,("republished printer\n"));
2370 if (info_enum[i].info2.devmode != NULL) {
2372 /* copy devmode (info level 2) */
2373 info_dst.info2.devmode = info_enum[i].info2.devmode;
2375 /* do not copy security descriptor (we have another
2376 * command for that) */
2377 info_dst.info2.secdesc = NULL;
2379 #if 0
2380 info_dst.info2.devmode.devicename =
2381 talloc_asprintf(mem_ctx, "\\\\%s\\%s",
2382 longname, printername);
2383 if (!info_dst.info2.devmode.devicename) {
2384 nt_status = NT_STATUS_NO_MEMORY;
2385 goto done;
2387 #endif
2388 if (!net_spoolss_setprinter(pipe_hnd_dst, mem_ctx, &hnd_dst,
2389 level, &info_dst))
2390 goto done;
2392 DEBUGADD(1,("\tSetPrinter of DEVICEMODE succeeded\n"));
2395 /* STEP 2: COPY REGISTRY VALUES */
2397 /* please keep in mind that samba parse_spools gives horribly
2398 crippled results when used to rpccli_spoolss_enumprinterdataex
2399 a win2k3-server. (Bugzilla #1851)
2400 FIXME: IIRC I've seen it too on a win2k-server
2403 r.in.handle = &hnd_src;
2404 r.in.enum_index = 0;
2405 r.in.value_offered = 0;
2406 r.in.data_offered = 0;
2407 r.out.value_name = NULL;
2408 r.out.value_needed = &value_needed;
2409 r.out.type = &type;
2410 r.out.data = NULL;
2411 r.out.data_needed = &data_needed;
2413 /* enumerate data on src handle */
2414 nt_status = dcerpc_spoolss_EnumPrinterData_r(b_src, mem_ctx, &r);
2416 r.in.data_offered = *r.out.data_needed;
2417 r.in.value_offered = *r.out.value_needed;
2418 r.out.data = talloc_zero_array(mem_ctx, uint8_t, r.in.data_offered);
2419 r.out.value_name = talloc_zero_array(mem_ctx, char, r.in.value_offered);
2421 /* loop for all printerdata of "PrinterDriverData" */
2422 while (NT_STATUS_IS_OK(nt_status) && W_ERROR_IS_OK(r.out.result)) {
2424 r.in.enum_index++;
2426 nt_status = dcerpc_spoolss_EnumPrinterData_r(b_src, mem_ctx, &r);
2428 /* loop for all reg_keys */
2429 if (NT_STATUS_IS_OK(nt_status) && W_ERROR_IS_OK(r.out.result)) {
2431 /* display_value */
2432 if (c->opt_verbose) {
2433 struct regval_blob *v;
2435 v = regval_compose(talloc_tos(),
2436 r.out.value_name,
2437 *r.out.type,
2438 r.out.data,
2439 r.in.data_offered);
2440 if (v == NULL) {
2441 nt_status = NT_STATUS_NO_MEMORY;
2442 goto done;
2445 display_reg_value(SPOOL_PRINTERDATA_KEY, v);
2446 talloc_free(v);
2449 /* set_value */
2450 if (!net_spoolss_setprinterdata(pipe_hnd_dst, mem_ctx,
2451 &hnd_dst, r.out.value_name,
2452 *r.out.type, r.out.data, r.in.data_offered))
2453 goto done;
2455 DEBUGADD(1,("\tSetPrinterData of [%s] succeeded\n",
2456 r.out.value_name));
2460 /* STEP 3: COPY SUBKEY VALUES */
2462 /* here we need to enum all printer_keys and then work
2463 on the result with enum_printer_key_ex. nt4 does not
2464 respond to enumprinterkey, win2k does, so continue
2465 in case of an error */
2467 if (!net_spoolss_enumprinterkey(pipe_hnd, mem_ctx, &hnd_src, "", &keylist)) {
2468 printf(_("got no key-data\n"));
2469 continue;
2473 /* work on a list of printer keys
2474 each key has to be enumerated to get all required
2475 information. information is then set via setprinterdataex-calls */
2477 if (keylist == NULL)
2478 continue;
2480 for (i=0; keylist && keylist[i] != NULL; i++) {
2482 const char *subkey = keylist[i];
2483 uint32_t count;
2484 struct spoolss_PrinterEnumValues *info;
2486 /* enumerate all src subkeys */
2487 if (!net_spoolss_enumprinterdataex(pipe_hnd, mem_ctx, 0,
2488 &hnd_src, subkey,
2489 &count, &info)) {
2490 goto done;
2493 for (j=0; j < count; j++) {
2495 struct regval_blob *value;
2496 DATA_BLOB blob;
2498 ZERO_STRUCT(blob);
2500 /* although samba replies with sane data in most cases we
2501 should try to avoid writing wrong registry data */
2503 if (strequal(info[j].value_name, SPOOL_REG_PORTNAME) ||
2504 strequal(info[j].value_name, SPOOL_REG_UNCNAME) ||
2505 strequal(info[j].value_name, SPOOL_REG_URL) ||
2506 strequal(info[j].value_name, SPOOL_REG_SHORTSERVERNAME) ||
2507 strequal(info[j].value_name, SPOOL_REG_SERVERNAME)) {
2509 if (strequal(info[j].value_name, SPOOL_REG_PORTNAME)) {
2511 /* although windows uses a multi-sz, we use a sz */
2512 push_reg_sz(mem_ctx, &blob, SAMBA_PRINTER_PORT_NAME);
2515 if (strequal(info[j].value_name, SPOOL_REG_UNCNAME)) {
2517 if (asprintf(&unc_name, "\\\\%s\\%s", longname, sharename) < 0) {
2518 nt_status = NT_STATUS_NO_MEMORY;
2519 goto done;
2521 push_reg_sz(mem_ctx, &blob, unc_name);
2524 if (strequal(info[j].value_name, SPOOL_REG_URL)) {
2526 continue;
2528 #if 0
2529 /* FIXME: should we really do that ??? */
2530 if (asprintf(&url, "http://%s:631/printers/%s", longname, sharename) < 0) {
2531 nt_status = NT_STATUS_NO_MEMORY;
2532 goto done;
2534 push_reg_sz(mem_ctx, NULL, &blob, url);
2535 fstrcpy(value.valuename, SPOOL_REG_URL);
2536 #endif
2539 if (strequal(info[j].value_name, SPOOL_REG_SERVERNAME)) {
2541 push_reg_sz(mem_ctx, &blob, longname);
2544 if (strequal(info[j].value_name, SPOOL_REG_SHORTSERVERNAME)) {
2546 push_reg_sz(mem_ctx, &blob, global_myname());
2549 value = regval_compose(talloc_tos(),
2550 info[j].value_name,
2551 REG_SZ,
2552 blob.length == 0 ? NULL : blob.data,
2553 blob.length);
2554 if (value == NULL) {
2555 nt_status = NT_STATUS_NO_MEMORY;
2556 goto done;
2559 if (c->opt_verbose)
2560 display_reg_value(subkey, value);
2562 /* here we have to set all subkeys on the dst server */
2563 if (!net_spoolss_setprinterdataex(pipe_hnd_dst, mem_ctx, &hnd_dst,
2564 subkey, value))
2566 talloc_free(value);
2567 goto done;
2570 talloc_free(value);
2571 } else {
2573 struct regval_blob *v;
2575 v = regval_compose(talloc_tos(),
2576 info[j].value_name,
2577 info[j].type,
2578 info[j].data->data,
2579 info[j].data->length);
2580 if (v == NULL) {
2581 nt_status = NT_STATUS_NO_MEMORY;
2582 goto done;
2585 if (c->opt_verbose) {
2586 display_reg_value(subkey, v);
2589 /* here we have to set all subkeys on the dst server */
2590 if (!net_spoolss_setprinterdataex(pipe_hnd_dst, mem_ctx, &hnd_dst,
2591 subkey, v)) {
2592 goto done;
2595 talloc_free(v);
2598 DEBUGADD(1,("\tSetPrinterDataEx of key [%s\\%s] succeeded\n",
2599 subkey, info[j].value_name));
2604 TALLOC_FREE(keylist);
2606 /* close printer handles here */
2607 if (is_valid_policy_hnd(&hnd_src)) {
2608 dcerpc_spoolss_ClosePrinter(b_src, mem_ctx, &hnd_src, &result);
2611 if (is_valid_policy_hnd(&hnd_dst)) {
2612 dcerpc_spoolss_ClosePrinter(b_dst, mem_ctx, &hnd_dst, &result);
2616 nt_status = NT_STATUS_OK;
2618 done:
2619 SAFE_FREE(devicename);
2620 SAFE_FREE(url);
2621 SAFE_FREE(unc_name);
2623 if (is_valid_policy_hnd(&hnd_src)) {
2624 dcerpc_spoolss_ClosePrinter(b_src, mem_ctx, &hnd_src, &result);
2627 if (is_valid_policy_hnd(&hnd_dst)) {
2628 dcerpc_spoolss_ClosePrinter(b_dst, mem_ctx, &hnd_dst, &result);
2631 if (cli_dst) {
2632 cli_shutdown(cli_dst);
2634 return nt_status;