torture3: Add some brlock entries in cleanup2
[Samba.git] / source3 / utils / net_rpc_printer.c
blobf5247b29352ddf9f7abf88f3059dc800f826bd4e
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 "system/filesys.h"
21 #include "utils/net.h"
22 #include "rpc_client/rpc_client.h"
23 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
24 #include "rpc_client/cli_spoolss.h"
25 #include "rpc_client/init_spoolss.h"
26 #include "nt_printing.h"
27 #include "registry.h"
28 #include "../libcli/security/security.h"
29 #include "../libcli/registry/util_reg.h"
30 #include "libsmb/libsmb.h"
31 #include "../libcli/smb/smbXcli_base.h"
33 /* support itanium as well */
34 static const struct print_architecture_table_node archi_table[]= {
36 {"Windows 4.0", "WIN40", 0 },
37 {"Windows NT x86", "W32X86", 2 },
38 {"Windows NT x86", "W32X86", 3 },
39 {"Windows NT R4000", "W32MIPS", 2 },
40 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
41 {"Windows NT PowerPC", "W32PPC", 2 },
42 {"Windows IA64", "IA64", 3 },
43 {"Windows x64", "x64", 3 },
44 {NULL, "", -1 }
48 /**
49 * This display-printdriver-functions was borrowed from rpcclient/cmd_spoolss.c.
50 * It is here for debugging purpose and should be removed later on.
51 **/
53 /****************************************************************************
54 Printer info level 3 display function.
55 ****************************************************************************/
57 static void display_print_driver3(struct spoolss_DriverInfo3 *r)
59 int i;
61 if (!r) {
62 return;
65 printf(_("Printer Driver Info 3:\n"));
66 printf(_("\tVersion: [%x]\n"), r->version);
67 printf(_("\tDriver Name: [%s]\n"), r->driver_name);
68 printf(_("\tArchitecture: [%s]\n"), r->architecture);
69 printf(_("\tDriver Path: [%s]\n"), r->driver_path);
70 printf(_("\tDatafile: [%s]\n"), r->data_file);
71 printf(_("\tConfigfile: [%s]\n\n"), r->config_file);
72 printf(_("\tHelpfile: [%s]\n\n"), r->help_file);
74 for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
75 printf(_("\tDependentfiles: [%s]\n"), r->dependent_files[i]);
78 printf("\n");
80 printf(_("\tMonitorname: [%s]\n"), r->monitor_name);
81 printf(_("\tDefaultdatatype: [%s]\n\n"), r->default_datatype);
84 static void display_reg_value(const char *subkey, const char *name, struct registry_value *value)
86 const char *text;
88 switch(value->type) {
89 case REG_DWORD:
90 if (value->data.length == sizeof(uint32)) {
91 d_printf(_("\t[%s:%s]: REG_DWORD: 0x%08x\n"), subkey,
92 name, IVAL(value->data.data,0));
93 } else {
94 d_printf(_("\t[%s:%s]: REG_DWORD: <invalid>\n"), subkey,
95 name);
97 break;
99 case REG_SZ:
100 pull_reg_sz(talloc_tos(), &value->data, &text);
101 if (!text) {
102 break;
104 d_printf(_("\t[%s:%s]: REG_SZ: %s\n"), subkey, name, text);
105 break;
107 case REG_BINARY:
108 d_printf(_("\t[%s:%s]: REG_BINARY: unknown length value not "
109 "displayed\n"),
110 subkey, name);
111 break;
113 case REG_MULTI_SZ: {
114 uint32_t i;
115 const char **values;
117 if (!pull_reg_multi_sz(NULL, &value->data, &values)) {
118 d_printf("pull_reg_multi_sz failed\n");
119 break;
122 printf("%s: REG_MULTI_SZ: \n", name);
123 for (i=0; values[i] != NULL; i++) {
124 d_printf("%s\n", values[i]);
126 TALLOC_FREE(values);
127 break;
130 default:
131 d_printf(_("\t%s: unknown type %d\n"), name, value->type);
137 * Copies ACLs, DOS-attributes and timestamps from one
138 * file or directory from one connected share to another connected share
140 * @param c A net_context structure
141 * @param mem_ctx A talloc-context
142 * @param cli_share_src A connected cli_state
143 * @param cli_share_dst A connected cli_state
144 * @param src_file The source file-name
145 * @param dst_file The destination file-name
146 * @param copy_acls Whether to copy acls
147 * @param copy_attrs Whether to copy DOS attributes
148 * @param copy_timestamps Whether to preserve timestamps
149 * @param is_file Whether this file is a file or a dir
151 * @return Normal NTSTATUS return.
154 NTSTATUS net_copy_fileattr(struct net_context *c,
155 TALLOC_CTX *mem_ctx,
156 struct cli_state *cli_share_src,
157 struct cli_state *cli_share_dst,
158 const char *src_name, const char *dst_name,
159 bool copy_acls, bool copy_attrs,
160 bool copy_timestamps, bool is_file)
162 NTSTATUS nt_status;
163 uint16_t fnum_src = 0;
164 uint16_t fnum_dst = 0;
165 struct security_descriptor *sd = NULL;
166 uint16_t attr;
167 time_t f_atime, f_ctime, f_mtime;
169 if (!copy_timestamps && !copy_acls && !copy_attrs)
170 return NT_STATUS_OK;
172 /* open file/dir on the originating server */
174 DEBUGADD(3,("opening %s %s on originating server\n",
175 is_file?"file":"dir", src_name));
177 nt_status = cli_ntcreate(cli_share_src, src_name, 0,
178 READ_CONTROL_ACCESS, 0,
179 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN,
180 0x0, 0x0, &fnum_src, NULL);
181 if (!NT_STATUS_IS_OK(nt_status)) {
182 DEBUGADD(0,("cannot open %s %s on originating server %s\n",
183 is_file?"file":"dir", src_name, nt_errstr(nt_status)));
184 goto out;
187 if (copy_acls) {
188 /* get the security descriptor */
189 nt_status = cli_query_secdesc(cli_share_src, fnum_src,
190 mem_ctx, &sd);
191 if (!NT_STATUS_IS_OK(nt_status)) {
192 DEBUG(0,("failed to get security descriptor: %s\n",
193 nt_errstr(nt_status)));
194 goto out;
197 if (c->opt_verbose && DEBUGLEVEL >= 3)
198 display_sec_desc(sd);
201 if (copy_attrs || copy_timestamps) {
203 /* get file attributes */
204 nt_status = cli_getattrE(cli_share_src, fnum_src, &attr, NULL,
205 &f_ctime, &f_atime, &f_mtime);
206 if (!NT_STATUS_IS_OK(nt_status)) {
207 DEBUG(0,("failed to get file-attrs: %s\n",
208 nt_errstr(nt_status)));
209 goto out;
213 /* open the file/dir on the destination server */
214 nt_status = cli_ntcreate(cli_share_dst, dst_name, 0,
215 WRITE_DAC_ACCESS | WRITE_OWNER_ACCESS, 0,
216 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN,
217 0x0, 0x0, &fnum_dst, NULL);
218 if (!NT_STATUS_IS_OK(nt_status)) {
219 DEBUG(0,("failed to open %s on the destination server: %s: %s\n",
220 is_file?"file":"dir", dst_name, nt_errstr(nt_status)));
221 goto out;
224 if (copy_timestamps) {
225 /* set timestamps */
226 nt_status = cli_setattrE(cli_share_dst, fnum_dst, f_ctime, f_atime, f_mtime);
227 if (!NT_STATUS_IS_OK(nt_status)) {
228 DEBUG(0,("failed to set file-attrs (timestamps): %s\n",
229 nt_errstr(nt_status)));
230 goto out;
234 if (copy_acls) {
235 /* set acls */
236 nt_status = cli_set_secdesc(cli_share_dst, fnum_dst, sd);
237 if (!NT_STATUS_IS_OK(nt_status)) {
238 DEBUG(0, ("could not set secdesc on %s: %s\n",
239 dst_name, nt_errstr(nt_status)));
240 goto out;
244 if (copy_attrs) {
245 /* set attrs */
246 nt_status = cli_setatr(cli_share_dst, dst_name, attr, 0);
247 if (!NT_STATUS_IS_OK(nt_status)) {
248 DEBUG(0,("failed to set file-attrs: %s\n",
249 nt_errstr(nt_status)));
250 goto out;
255 /* closing files */
256 nt_status = cli_close(cli_share_src, fnum_src);
257 if (!NT_STATUS_IS_OK(nt_status)) {
258 d_fprintf(stderr,
259 _("could not close %s on originating server: %s\n"),
260 is_file?"file":"dir", nt_errstr(nt_status));
261 goto out;
264 nt_status = cli_close(cli_share_dst, fnum_dst);
265 if (!NT_STATUS_IS_OK(nt_status)) {
266 d_fprintf(stderr,
267 _("could not close %s on destination server: %s\n"),
268 is_file?"file":"dir", nt_errstr(nt_status));
269 goto out;
273 nt_status = NT_STATUS_OK;
275 out:
277 /* cleaning up */
278 if (fnum_src)
279 cli_close(cli_share_src, fnum_src);
281 if (fnum_dst)
282 cli_close(cli_share_dst, fnum_dst);
284 return nt_status;
288 * Copy a file or directory from a connected share to another connected share
290 * @param c A net_context structure
291 * @param mem_ctx A talloc-context
292 * @param cli_share_src A connected cli_state
293 * @param cli_share_dst A connected cli_state
294 * @param src_file The source file-name
295 * @param dst_file The destination file-name
296 * @param copy_acls Whether to copy acls
297 * @param copy_attrs Whether to copy DOS attributes
298 * @param copy_timestamps Whether to preserve timestamps
299 * @param is_file Whether this file is a file or a dir
301 * @return Normal NTSTATUS return.
304 NTSTATUS net_copy_file(struct net_context *c,
305 TALLOC_CTX *mem_ctx,
306 struct cli_state *cli_share_src,
307 struct cli_state *cli_share_dst,
308 const char *src_name, const char *dst_name,
309 bool copy_acls, bool copy_attrs,
310 bool copy_timestamps, bool is_file)
312 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
313 uint16_t fnum_src = 0;
314 uint16_t fnum_dst = 0;
315 static int io_bufsize = 64512;
316 int read_size = io_bufsize;
317 char *data = NULL;
318 off_t nread = 0;
321 if (!src_name || !dst_name)
322 goto out;
324 if (cli_share_src == NULL || cli_share_dst == NULL)
325 goto out;
327 /* open on the originating server */
328 DEBUGADD(3,("opening %s %s on originating server\n",
329 is_file ? "file":"dir", src_name));
330 if (is_file)
331 nt_status = cli_open(cli_share_src, src_name, O_RDONLY, DENY_NONE, &fnum_src);
332 else
333 nt_status = cli_ntcreate(cli_share_src, src_name, 0, READ_CONTROL_ACCESS, 0,
334 FILE_SHARE_READ|FILE_SHARE_WRITE,
335 FILE_OPEN, 0x0, 0x0, &fnum_src, NULL);
337 if (!NT_STATUS_IS_OK(nt_status)) {
338 DEBUGADD(0,("cannot open %s %s on originating server %s\n",
339 is_file ? "file":"dir",
340 src_name, nt_errstr(nt_status)));
341 goto out;
345 if (is_file) {
347 /* open file on the destination server */
348 DEBUGADD(3,("opening file %s on destination server\n", dst_name));
349 nt_status = cli_open(cli_share_dst, dst_name,
350 O_RDWR|O_CREAT|O_TRUNC, DENY_NONE, &fnum_dst);
352 if (!NT_STATUS_IS_OK(nt_status)) {
353 DEBUGADD(1,("cannot create file %s on destination server: %s\n",
354 dst_name, nt_errstr(nt_status)));
355 goto out;
358 /* allocate memory */
359 if (!(data = (char *)SMB_MALLOC(read_size))) {
360 d_fprintf(stderr, _("malloc fail for size %d\n"),
361 read_size);
362 nt_status = NT_STATUS_NO_MEMORY;
363 goto out;
369 if (c->opt_verbose) {
371 d_printf(_("copying [\\\\%s\\%s%s] => [\\\\%s\\%s%s] "
372 "%s ACLs and %s DOS Attributes %s\n"),
373 smbXcli_conn_remote_name(cli_share_src->conn),
374 cli_share_src->share, src_name,
375 smbXcli_conn_remote_name(cli_share_dst->conn),
376 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 size_t n;
388 nt_status = cli_read(cli_share_src, fnum_src, data, nread,
389 read_size, &n);
390 if (!NT_STATUS_IS_OK(nt_status)) {
391 d_fprintf(stderr,
392 _("Error reading file [\\\\%s\\%s%s]: %s\n"),
393 smbXcli_conn_remote_name(cli_share_src->conn),
394 cli_share_src->share,
395 src_name, nt_errstr(nt_status));
396 goto out;
399 if (n == 0)
400 break;
402 nt_status = cli_writeall(cli_share_dst, fnum_dst, 0,
403 (uint8_t *)data, nread, n, NULL);
405 if (!NT_STATUS_IS_OK(nt_status)) {
406 d_fprintf(stderr,
407 _("Error writing file: [\\\\%s\\%s%s]: %s\n"),
408 smbXcli_conn_remote_name(cli_share_dst->conn),
409 cli_share_dst->share,
410 dst_name, nt_errstr(nt_status));
411 goto out;
414 nread += n;
418 if (!is_file && !NT_STATUS_IS_OK(cli_chkpath(cli_share_dst, dst_name))) {
420 /* creating dir */
421 DEBUGADD(3,("creating dir %s on the destination server\n",
422 dst_name));
424 nt_status = cli_mkdir(cli_share_dst, dst_name);
425 if (!NT_STATUS_IS_OK(nt_status)) {
426 DEBUG(0,("cannot create directory %s: %s\n",
427 dst_name, nt_errstr(nt_status)));
428 nt_status = NT_STATUS_NO_SUCH_FILE;
432 nt_status = cli_chkpath(cli_share_dst, dst_name);
433 if (!NT_STATUS_IS_OK(nt_status)) {
434 d_fprintf(stderr,
435 _("cannot check for directory %s: %s\n"),
436 dst_name, nt_errstr(nt_status));
437 goto out;
442 /* closing files */
443 nt_status = cli_close(cli_share_src, fnum_src);
444 if (!NT_STATUS_IS_OK(nt_status)) {
445 d_fprintf(stderr,
446 _("could not close file on originating server: %s\n"),
447 nt_errstr(nt_status));
448 goto out;
451 if (is_file) {
452 nt_status = cli_close(cli_share_dst, fnum_dst);
453 if (!NT_STATUS_IS_OK(nt_status)) {
454 d_fprintf(stderr,
455 _("could not close file on destination server: %s\n"),
456 nt_errstr(nt_status));
457 goto out;
461 /* possibly we have to copy some file-attributes / acls / sd */
462 nt_status = net_copy_fileattr(c, mem_ctx, cli_share_src, cli_share_dst,
463 src_name, dst_name, copy_acls,
464 copy_attrs, copy_timestamps, is_file);
465 if (!NT_STATUS_IS_OK(nt_status))
466 goto out;
469 nt_status = NT_STATUS_OK;
471 out:
473 /* cleaning up */
474 if (fnum_src)
475 cli_close(cli_share_src, fnum_src);
477 if (fnum_dst)
478 cli_close(cli_share_dst, fnum_dst);
480 SAFE_FREE(data);
482 return nt_status;
486 * Copy a driverfile from on connected share to another connected share
487 * This silently assumes that a driver-file is picked up from
489 * \\src_server\print$\{arch}\{version}\file
491 * and copied to
493 * \\dst_server\print$\{arch}\file
495 * to be added via setdriver-calls later.
496 * @param c A net_context structure
497 * @param mem_ctx A talloc-context
498 * @param cli_share_src A cli_state connected to source print$-share
499 * @param cli_share_dst A cli_state connected to destination print$-share
500 * @param file The file-name to be copied
501 * @param short_archi The name of the driver-architecture (short form)
503 * @return Normal NTSTATUS return.
506 static NTSTATUS net_copy_driverfile(struct net_context *c,
507 TALLOC_CTX *mem_ctx,
508 struct cli_state *cli_share_src,
509 struct cli_state *cli_share_dst,
510 const char *file, const char *short_archi) {
512 const char *p;
513 char *src_name;
514 char *dst_name;
515 char *version = NULL;
516 char *filename = NULL;
517 char *tok;
519 if (!file) {
520 return NT_STATUS_OK;
523 /* scroll through the file until we have the part
524 beyond archi_table.short_archi */
525 p = file;
526 while (next_token_talloc(mem_ctx, &p, &tok, "\\")) {
527 if (strequal(tok, short_archi)) {
528 next_token_talloc(mem_ctx, &p, &version, "\\");
529 next_token_talloc(mem_ctx, &p, &filename, "\\");
533 if (version == NULL || filename == NULL) {
534 return NT_STATUS_UNSUCCESSFUL;
537 /* build source file name */
538 src_name = talloc_asprintf(mem_ctx, "\\%s\\%s\\%s",
539 short_archi, version, filename);
540 if (src_name == NULL) {
541 return NT_STATUS_NO_MEMORY;
544 /* create destination file name */
545 dst_name = talloc_asprintf(mem_ctx, "\\%s\\%s", short_archi, filename);
546 if (dst_name == NULL) {
547 return NT_STATUS_NO_MEMORY;
551 /* finally copy the file */
552 return net_copy_file(c, mem_ctx, cli_share_src, cli_share_dst,
553 src_name, dst_name, false, false, false, true);
557 * Check for existing Architecture directory on a given server
559 * @param cli_share A cli_state connected to a print$-share
560 * @param short_archi The Architecture for the print-driver
562 * @return Normal NTSTATUS return.
565 static NTSTATUS check_arch_dir(struct cli_state *cli_share, const char *short_archi)
568 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
569 char *dir;
571 if (asprintf(&dir, "\\%s", short_archi) < 0) {
572 return NT_STATUS_NO_MEMORY;
575 DEBUG(10,("creating print-driver dir for architecture: %s\n",
576 short_archi));
578 nt_status = cli_mkdir(cli_share, dir);
579 if (!NT_STATUS_IS_OK(nt_status)) {
580 DEBUG(1,("cannot create directory %s: %s\n",
581 dir, nt_errstr(nt_status)));
584 nt_status = cli_chkpath(cli_share, dir);
585 if (!NT_STATUS_IS_OK(nt_status)) {
586 d_fprintf(stderr, _("cannot check %s: %s\n"),
587 dir, nt_errstr(nt_status));
588 goto out;
591 nt_status = NT_STATUS_OK;
593 out:
594 SAFE_FREE(dir);
595 return nt_status;
599 * Copy a print-driver (level 3) from one connected print$-share to another
600 * connected print$-share
602 * @param c A net_context structure
603 * @param mem_ctx A talloc-context
604 * @param cli_share_src A cli_state connected to a print$-share
605 * @param cli_share_dst A cli_state connected to a print$-share
606 * @param short_archi The Architecture for the print-driver
607 * @param i1 The DRIVER_INFO_3-struct
609 * @return Normal NTSTATUS return.
612 static NTSTATUS copy_print_driver_3(struct net_context *c,
613 TALLOC_CTX *mem_ctx,
614 struct cli_state *cli_share_src,
615 struct cli_state *cli_share_dst,
616 const char *short_archi,
617 struct spoolss_DriverInfo3 *r)
619 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
620 int i;
622 if (r == NULL) {
623 return nt_status;
626 if (c->opt_verbose)
627 d_printf(_("copying driver: [%s], for architecture: [%s], "
628 "version: [%d]\n"),
629 r->driver_name, short_archi, r->version);
631 nt_status = net_copy_driverfile(c, mem_ctx, cli_share_src, cli_share_dst,
632 r->driver_path, short_archi);
633 if (!NT_STATUS_IS_OK(nt_status))
634 return nt_status;
636 nt_status = net_copy_driverfile(c, mem_ctx, cli_share_src, cli_share_dst,
637 r->data_file, short_archi);
638 if (!NT_STATUS_IS_OK(nt_status))
639 return nt_status;
641 nt_status = net_copy_driverfile(c, mem_ctx, cli_share_src, cli_share_dst,
642 r->config_file, short_archi);
643 if (!NT_STATUS_IS_OK(nt_status))
644 return nt_status;
646 nt_status = net_copy_driverfile(c, mem_ctx, cli_share_src, cli_share_dst,
647 r->help_file, short_archi);
648 if (!NT_STATUS_IS_OK(nt_status))
649 return nt_status;
651 for (i=0; r->dependent_files[i] != NULL; i++) {
653 nt_status = net_copy_driverfile(c, mem_ctx,
654 cli_share_src, cli_share_dst,
655 r->dependent_files[i], short_archi);
656 if (!NT_STATUS_IS_OK(nt_status)) {
657 return nt_status;
661 return NT_STATUS_OK;
665 * net_spoolss-functions
666 * =====================
668 * the net_spoolss-functions aim to simplify spoolss-client-functions
669 * required during the migration-process wrt buffer-sizes, returned
670 * error-codes, etc.
672 * this greatly reduces the complexitiy of the migrate-functions.
676 static bool net_spoolss_enum_printers(struct rpc_pipe_client *pipe_hnd,
677 TALLOC_CTX *mem_ctx,
678 char *name,
679 uint32_t flags,
680 uint32_t level,
681 uint32_t *num_printers,
682 union spoolss_PrinterInfo **info)
684 WERROR result;
686 /* enum printers */
688 result = rpccli_spoolss_enumprinters(pipe_hnd, mem_ctx,
689 flags,
690 name,
691 level,
693 num_printers,
694 info);
695 if (!W_ERROR_IS_OK(result)) {
696 printf(_("cannot enum printers: %s\n"), win_errstr(result));
697 return false;
700 return true;
703 static bool net_spoolss_open_printer_ex(struct rpc_pipe_client *pipe_hnd,
704 TALLOC_CTX *mem_ctx,
705 const char *printername,
706 uint32_t access_required,
707 const char *username,
708 struct policy_handle *hnd)
710 WERROR result;
711 fstring printername2;
713 fstrcpy(printername2, pipe_hnd->srv_name_slash);
714 fstrcat(printername2, "\\");
715 fstrcat(printername2, printername);
717 DEBUG(10,("connecting to: %s as %s for %s and access: %x\n",
718 pipe_hnd->srv_name_slash, username, printername2, access_required));
720 /* open printer */
721 result = rpccli_spoolss_openprinter_ex(pipe_hnd, mem_ctx,
722 printername2,
723 access_required,
724 hnd);
726 /* be more verbose */
727 if (W_ERROR_V(result) == W_ERROR_V(WERR_ACCESS_DENIED)) {
728 d_fprintf(stderr,
729 _("no access to printer [%s] on [%s] for user [%s] "
730 "granted\n"),
731 printername2, pipe_hnd->srv_name_slash, username);
732 return false;
735 if (!W_ERROR_IS_OK(result)) {
736 d_fprintf(stderr,_("cannot open printer %s on server %s: %s\n"),
737 printername2, pipe_hnd->srv_name_slash, win_errstr(result));
738 return false;
741 DEBUG(2,("got printer handle for printer: %s, server: %s\n",
742 printername2, pipe_hnd->srv_name_slash));
744 return true;
747 static bool net_spoolss_getprinter(struct rpc_pipe_client *pipe_hnd,
748 TALLOC_CTX *mem_ctx,
749 struct policy_handle *hnd,
750 uint32_t level,
751 union spoolss_PrinterInfo *info)
753 WERROR result;
755 /* getprinter call */
756 result = rpccli_spoolss_getprinter(pipe_hnd, mem_ctx,
757 hnd,
758 level,
759 0, /* offered */
760 info);
761 if (!W_ERROR_IS_OK(result)) {
762 printf(_("cannot get printer-info: %s\n"), win_errstr(result));
763 return false;
766 return true;
769 static bool net_spoolss_setprinter(struct rpc_pipe_client *pipe_hnd,
770 TALLOC_CTX *mem_ctx,
771 struct policy_handle *hnd,
772 uint32_t level,
773 union spoolss_PrinterInfo *info)
775 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
776 WERROR result;
777 NTSTATUS status;
778 struct spoolss_SetPrinterInfoCtr info_ctr;
779 struct spoolss_SetPrinterInfo2 info2;
780 struct spoolss_DevmodeContainer devmode_ctr;
781 struct sec_desc_buf secdesc_ctr;
783 ZERO_STRUCT(devmode_ctr);
784 ZERO_STRUCT(secdesc_ctr);
786 /* setprinter call */
788 info_ctr.level = level;
789 switch (level) {
790 case 0:
791 info_ctr.info.info0 = (struct spoolss_SetPrinterInfo0 *)
792 (void *)&info->info0;
793 break;
794 case 1:
795 info_ctr.info.info1 = (struct spoolss_SetPrinterInfo1 *)
796 (void *)&info->info1;
797 break;
798 case 2:
799 spoolss_printerinfo2_to_setprinterinfo2(&info->info2, &info2);
800 info_ctr.info.info2 = &info2;
801 break;
802 case 3:
803 info_ctr.info.info3 = (struct spoolss_SetPrinterInfo3 *)
804 (void *)&info->info3;
805 break;
806 case 4:
807 info_ctr.info.info4 = (struct spoolss_SetPrinterInfo4 *)
808 (void *)&info->info4;
809 break;
810 case 5:
811 info_ctr.info.info5 = (struct spoolss_SetPrinterInfo5 *)
812 (void *)&info->info5;
813 break;
814 case 6:
815 info_ctr.info.info6 = (struct spoolss_SetPrinterInfo6 *)
816 (void *)&info->info6;
817 break;
818 case 7:
819 info_ctr.info.info7 = (struct spoolss_SetPrinterInfo7 *)
820 (void *)&info->info7;
821 break;
822 #if 0 /* FIXME GD */
823 case 8:
824 info_ctr.info.info8 = (struct spoolss_SetPrinterInfo8 *)
825 (void *)&info->info8;
826 break;
827 case 9:
828 info_ctr.info.info9 = (struct spoolss_SetPrinterInfo9 *)
829 (void *)&info->info9;
830 break;
831 #endif
832 default:
833 break; /* FIXME */
836 status = dcerpc_spoolss_SetPrinter(b, mem_ctx,
837 hnd,
838 &info_ctr,
839 &devmode_ctr,
840 &secdesc_ctr,
841 0, /* command */
842 &result);
843 if (!NT_STATUS_IS_OK(status)) {
844 printf(_("cannot set printer-info: %s\n"), nt_errstr(status));
845 return false;
847 if (!W_ERROR_IS_OK(result)) {
848 printf(_("cannot set printer-info: %s\n"), win_errstr(result));
849 return false;
852 return true;
856 static bool net_spoolss_setprinterdata(struct rpc_pipe_client *pipe_hnd,
857 TALLOC_CTX *mem_ctx,
858 struct policy_handle *hnd,
859 const char *value_name,
860 enum winreg_Type type,
861 uint8_t *data,
862 uint32_t offered)
864 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
865 WERROR result;
866 NTSTATUS status;
868 /* setprinterdata call */
869 status = dcerpc_spoolss_SetPrinterData(b, mem_ctx,
870 hnd,
871 value_name,
872 type,
873 data,
874 offered,
875 &result);
876 if (!NT_STATUS_IS_OK(status)) {
877 printf (_("unable to set printerdata: %s\n"),
878 nt_errstr(status));
879 return false;
881 if (!W_ERROR_IS_OK(result)) {
882 printf (_("unable to set printerdata: %s\n"),
883 win_errstr(result));
884 return false;
887 return true;
891 static bool net_spoolss_enumprinterkey(struct rpc_pipe_client *pipe_hnd,
892 TALLOC_CTX *mem_ctx,
893 struct policy_handle *hnd,
894 const char *keyname,
895 const char ***keylist)
897 WERROR result;
899 /* enumprinterkey call */
900 result = rpccli_spoolss_enumprinterkey(pipe_hnd, mem_ctx, hnd, keyname, keylist, 0);
902 if (!W_ERROR_IS_OK(result)) {
903 printf(_("enumprinterkey failed: %s\n"), win_errstr(result));
904 return false;
907 return true;
910 static bool net_spoolss_enumprinterdataex(struct rpc_pipe_client *pipe_hnd,
911 TALLOC_CTX *mem_ctx,
912 uint32_t offered,
913 struct policy_handle *hnd,
914 const char *keyname,
915 uint32_t *count,
916 struct spoolss_PrinterEnumValues **info)
918 WERROR result;
920 /* enumprinterdataex call */
921 result = rpccli_spoolss_enumprinterdataex(pipe_hnd, mem_ctx,
922 hnd,
923 keyname,
924 0, /* offered */
925 count,
926 info);
928 if (!W_ERROR_IS_OK(result)) {
929 printf(_("enumprinterdataex failed: %s\n"), win_errstr(result));
930 return false;
933 return true;
937 static bool net_spoolss_setprinterdataex(struct rpc_pipe_client *pipe_hnd,
938 TALLOC_CTX *mem_ctx,
939 struct policy_handle *hnd,
940 const char *keyname,
941 const char *name,
942 struct registry_value *value)
944 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
945 WERROR result;
946 NTSTATUS status;
948 /* setprinterdataex call */
949 status = dcerpc_spoolss_SetPrinterDataEx(b, mem_ctx,
950 hnd,
951 keyname,
952 name,
953 value->type,
954 value->data.data,
955 value->data.length,
956 &result);
957 if (!NT_STATUS_IS_OK(status)) {
958 printf(_("could not set printerdataex: %s\n"),
959 nt_errstr(status));
960 return false;
962 if (!W_ERROR_IS_OK(result)) {
963 printf(_("could not set printerdataex: %s\n"),
964 win_errstr(result));
965 return false;
968 return true;
971 static bool net_spoolss_enumforms(struct rpc_pipe_client *pipe_hnd,
972 TALLOC_CTX *mem_ctx,
973 struct policy_handle *hnd,
974 int level,
975 uint32_t *num_forms,
976 union spoolss_FormInfo **forms)
978 WERROR result;
980 /* enumforms call */
981 result = rpccli_spoolss_enumforms(pipe_hnd, mem_ctx,
982 hnd,
983 level,
985 num_forms,
986 forms);
987 if (!W_ERROR_IS_OK(result)) {
988 printf(_("could not enum forms: %s\n"), win_errstr(result));
989 return false;
992 return true;
995 static bool net_spoolss_enumprinterdrivers (struct rpc_pipe_client *pipe_hnd,
996 TALLOC_CTX *mem_ctx,
997 uint32_t level, const char *env,
998 uint32_t *count,
999 union spoolss_DriverInfo **info)
1001 WERROR result;
1003 /* enumprinterdrivers call */
1004 result = rpccli_spoolss_enumprinterdrivers(pipe_hnd, mem_ctx,
1005 pipe_hnd->srv_name_slash,
1006 env,
1007 level,
1009 count,
1010 info);
1011 if (!W_ERROR_IS_OK(result)) {
1012 if (W_ERROR_V(result) != W_ERROR_V(WERR_INVALID_ENVIRONMENT)) {
1013 printf(_("cannot enum drivers for environment %s: %s\n"), env,
1014 win_errstr(result));
1015 return false;
1016 } else {
1017 printf(_("Server does not support environment [%s]\n"),
1018 env);
1022 return true;
1025 static bool net_spoolss_getprinterdriver(struct rpc_pipe_client *pipe_hnd,
1026 TALLOC_CTX *mem_ctx,
1027 struct policy_handle *hnd, uint32_t level,
1028 const char *env, int version,
1029 union spoolss_DriverInfo *info)
1031 WERROR result;
1032 uint32_t server_major_version;
1033 uint32_t server_minor_version;
1035 /* getprinterdriver call */
1036 result = rpccli_spoolss_getprinterdriver2(pipe_hnd, mem_ctx,
1037 hnd,
1038 env,
1039 level,
1041 version,
1043 info,
1044 &server_major_version,
1045 &server_minor_version);
1046 if (!W_ERROR_IS_OK(result)) {
1047 DEBUG(1,("cannot get driver (for architecture: %s): %s\n",
1048 env, win_errstr(result)));
1049 if (W_ERROR_V(result) != W_ERROR_V(WERR_UNKNOWN_PRINTER_DRIVER) &&
1050 W_ERROR_V(result) != W_ERROR_V(WERR_INVALID_ENVIRONMENT)) {
1051 printf(_("cannot get driver: %s\n"),
1052 win_errstr(result));
1054 return false;
1057 return true;
1061 static bool net_spoolss_addprinterdriver(struct rpc_pipe_client *pipe_hnd,
1062 TALLOC_CTX *mem_ctx, uint32_t level,
1063 union spoolss_DriverInfo *info)
1065 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
1066 WERROR result;
1067 NTSTATUS status;
1068 struct spoolss_AddDriverInfoCtr info_ctr;
1070 info_ctr.level = level;
1072 switch (level) {
1073 case 2:
1074 info_ctr.info.info2 = (struct spoolss_AddDriverInfo2 *)
1075 (void *)&info->info2;
1076 break;
1077 case 3:
1078 info_ctr.info.info3 = (struct spoolss_AddDriverInfo3 *)
1079 (void *)&info->info3;
1080 break;
1081 default:
1082 printf(_("unsupported info level: %d\n"), level);
1083 return false;
1086 /* addprinterdriver call */
1087 status = dcerpc_spoolss_AddPrinterDriver(b, mem_ctx,
1088 pipe_hnd->srv_name_slash,
1089 &info_ctr,
1090 &result);
1091 if (!NT_STATUS_IS_OK(status)) {
1092 printf(_("cannot add driver: %s\n"), nt_errstr(status));
1093 return false;
1095 /* be more verbose */
1096 if (W_ERROR_V(result) == W_ERROR_V(WERR_ACCESS_DENIED)) {
1097 printf(_("You are not allowed to add drivers\n"));
1098 return false;
1100 if (!W_ERROR_IS_OK(result)) {
1101 printf(_("cannot add driver: %s\n"), win_errstr(result));
1102 return false;
1105 return true;
1109 * abstraction function to get uint32_t num_printers and PRINTER_INFO_CTR ctr
1110 * for a single printer or for all printers depending on argc/argv
1113 static bool get_printer_info(struct rpc_pipe_client *pipe_hnd,
1114 TALLOC_CTX *mem_ctx,
1115 int level,
1116 int argc,
1117 const char **argv,
1118 uint32_t *num_printers,
1119 union spoolss_PrinterInfo **info_p)
1121 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
1122 struct policy_handle hnd;
1123 WERROR werr;
1125 /* no arguments given, enumerate all printers */
1126 if (argc == 0) {
1128 if (!net_spoolss_enum_printers(pipe_hnd, mem_ctx, NULL,
1129 PRINTER_ENUM_LOCAL|PRINTER_ENUM_SHARED,
1130 level, num_printers, info_p))
1131 return false;
1133 goto out;
1136 /* argument given, get a single printer by name */
1137 if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, argv[0],
1138 MAXIMUM_ALLOWED_ACCESS,
1139 pipe_hnd->auth->user_name,
1140 &hnd))
1141 return false;
1143 *info_p = talloc_zero(mem_ctx, union spoolss_PrinterInfo);
1144 if (*info_p == NULL) {
1145 return false;
1148 if (!net_spoolss_getprinter(pipe_hnd, mem_ctx, &hnd, level, *info_p)) {
1149 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &werr);
1150 return false;
1153 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &werr);
1155 *num_printers = 1;
1157 out:
1158 DEBUG(3,("got %d printers\n", *num_printers));
1160 return true;
1165 * List print-queues (including local printers that are not shared)
1167 * All parameters are provided by the run_rpc_command function, except for
1168 * argc, argv which are passed through.
1170 * @param c A net_context structure
1171 * @param domain_sid The domain sid aquired from the remote server
1172 * @param cli A cli_state connected to the server.
1173 * @param mem_ctx Talloc context, destoyed on compleation of the function.
1174 * @param argc Standard main() style argc
1175 * @param argv Standard main() style argv. Initial components are already
1176 * stripped
1178 * @return Normal NTSTATUS return.
1181 NTSTATUS rpc_printer_list_internals(struct net_context *c,
1182 const struct dom_sid *domain_sid,
1183 const char *domain_name,
1184 struct cli_state *cli,
1185 struct rpc_pipe_client *pipe_hnd,
1186 TALLOC_CTX *mem_ctx,
1187 int argc,
1188 const char **argv)
1190 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1191 uint32_t i, num_printers;
1192 uint32_t level = 2;
1193 const char *printername, *sharename;
1194 union spoolss_PrinterInfo *info;
1196 printf("listing printers\n");
1198 if (!get_printer_info(pipe_hnd, mem_ctx, level, argc, argv, &num_printers, &info))
1199 return nt_status;
1201 for (i = 0; i < num_printers; i++) {
1203 /* do some initialization */
1204 printername = info[i].info2.printername;
1205 sharename = info[i].info2.sharename;
1207 if (printername && sharename) {
1208 d_printf(_("printer %d: %s, shared as: %s\n"),
1209 i+1, printername, sharename);
1213 return NT_STATUS_OK;
1217 * List printer-drivers from a server
1219 * All parameters are provided by the run_rpc_command function, except for
1220 * argc, argv which are passed through.
1222 * @param c A net_context structure
1223 * @param domain_sid The domain sid aquired from the remote server
1224 * @param cli A cli_state connected to the server.
1225 * @param mem_ctx Talloc context, destoyed on compleation of the function.
1226 * @param argc Standard main() style argc
1227 * @param argv Standard main() style argv. Initial components are already
1228 * stripped
1230 * @return Normal NTSTATUS return.
1233 NTSTATUS rpc_printer_driver_list_internals(struct net_context *c,
1234 const struct dom_sid *domain_sid,
1235 const char *domain_name,
1236 struct cli_state *cli,
1237 struct rpc_pipe_client *pipe_hnd,
1238 TALLOC_CTX *mem_ctx,
1239 int argc,
1240 const char **argv)
1242 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1243 uint32_t i;
1244 uint32_t level = 3;
1245 union spoolss_DriverInfo *info;
1246 int d;
1248 printf(_("listing printer-drivers\n"));
1250 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1252 uint32_t num_drivers;
1254 /* enum remote drivers */
1255 if (!net_spoolss_enumprinterdrivers(pipe_hnd, mem_ctx, level,
1256 archi_table[i].long_archi,
1257 &num_drivers, &info)) {
1258 nt_status = NT_STATUS_UNSUCCESSFUL;
1259 goto done;
1262 if (num_drivers == 0) {
1263 d_printf(_("no drivers found on server for "
1264 "architecture: [%s].\n"),
1265 archi_table[i].long_archi);
1266 continue;
1269 d_printf(_("got %d printer-drivers for architecture: [%s]\n"),
1270 num_drivers, archi_table[i].long_archi);
1273 /* do something for all drivers for architecture */
1274 for (d = 0; d < num_drivers; d++) {
1275 display_print_driver3(&info[d].info3);
1279 nt_status = NT_STATUS_OK;
1281 done:
1282 return nt_status;
1287 * Publish print-queues with args-wrapper
1289 * @param cli A cli_state connected to the server.
1290 * @param mem_ctx Talloc context, destoyed on compleation of the function.
1291 * @param argc Standard main() style argc
1292 * @param argv Standard main() style argv. Initial components are already
1293 * stripped
1294 * @param action
1296 * @return Normal NTSTATUS return.
1299 static NTSTATUS rpc_printer_publish_internals_args(struct rpc_pipe_client *pipe_hnd,
1300 TALLOC_CTX *mem_ctx,
1301 int argc,
1302 const char **argv,
1303 uint32_t action)
1305 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
1306 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1307 uint32_t i, num_printers;
1308 uint32_t level = 7;
1309 const char *printername, *sharename;
1310 union spoolss_PrinterInfo *info_enum;
1311 union spoolss_PrinterInfo info;
1312 struct spoolss_SetPrinterInfoCtr info_ctr;
1313 struct spoolss_DevmodeContainer devmode_ctr;
1314 struct sec_desc_buf secdesc_ctr;
1315 struct policy_handle hnd = { 0, };
1316 WERROR result;
1317 const char *action_str;
1319 if (!get_printer_info(pipe_hnd, mem_ctx, 2, argc, argv, &num_printers, &info_enum))
1320 return nt_status;
1322 for (i = 0; i < num_printers; i++) {
1324 /* do some initialization */
1325 printername = info_enum[i].info2.printername;
1326 sharename = info_enum[i].info2.sharename;
1327 if (!printername || !sharename) {
1328 goto done;
1331 /* open printer handle */
1332 if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, sharename,
1333 PRINTER_ALL_ACCESS, pipe_hnd->auth->user_name, &hnd))
1334 goto done;
1336 /* check for existing dst printer */
1337 if (!net_spoolss_getprinter(pipe_hnd, mem_ctx, &hnd, level, &info))
1338 goto done;
1340 /* check action and set string */
1341 switch (action) {
1342 case DSPRINT_PUBLISH:
1343 action_str = N_("published");
1344 break;
1345 case DSPRINT_UPDATE:
1346 action_str = N_("updated");
1347 break;
1348 case DSPRINT_UNPUBLISH:
1349 action_str = N_("unpublished");
1350 break;
1351 default:
1352 action_str = N_("unknown action");
1353 printf(_("unknown action: %d\n"), action);
1354 break;
1357 info.info7.action = action;
1358 info_ctr.level = 7;
1359 info_ctr.info.info7 = (struct spoolss_SetPrinterInfo7 *)
1360 (void *)&info.info7;
1362 ZERO_STRUCT(devmode_ctr);
1363 ZERO_STRUCT(secdesc_ctr);
1365 nt_status = dcerpc_spoolss_SetPrinter(b, mem_ctx,
1366 &hnd,
1367 &info_ctr,
1368 &devmode_ctr,
1369 &secdesc_ctr,
1370 0, /* command */
1371 &result);
1372 if (!NT_STATUS_IS_OK(nt_status)) {
1373 printf(_("cannot set printer-info: %s\n"),
1374 nt_errstr(nt_status));
1375 goto done;
1377 if (!W_ERROR_IS_OK(result) && !W_ERROR_EQUAL(result, WERR_IO_PENDING)) {
1378 if ((action == DSPRINT_UPDATE) && W_ERROR_EQUAL(result, W_ERROR(0x80070002))) {
1379 printf(_("printer not published yet\n"));
1380 } else {
1381 printf(_("cannot set printer-info: %s\n"),
1382 win_errstr(result));
1384 nt_status = werror_to_ntstatus(result);
1385 goto done;
1388 printf(_("successfully %s printer %s in Active Directory\n"),
1389 action_str, sharename);
1392 nt_status = NT_STATUS_OK;
1394 done:
1395 if (is_valid_policy_hnd(&hnd)) {
1396 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &result);
1399 return nt_status;
1402 NTSTATUS rpc_printer_publish_publish_internals(struct net_context *c,
1403 const struct dom_sid *domain_sid,
1404 const char *domain_name,
1405 struct cli_state *cli,
1406 struct rpc_pipe_client *pipe_hnd,
1407 TALLOC_CTX *mem_ctx,
1408 int argc,
1409 const char **argv)
1411 return rpc_printer_publish_internals_args(pipe_hnd, mem_ctx, argc, argv, DSPRINT_PUBLISH);
1414 NTSTATUS rpc_printer_publish_unpublish_internals(struct net_context *c,
1415 const struct dom_sid *domain_sid,
1416 const char *domain_name,
1417 struct cli_state *cli,
1418 struct rpc_pipe_client *pipe_hnd,
1419 TALLOC_CTX *mem_ctx,
1420 int argc,
1421 const char **argv)
1423 return rpc_printer_publish_internals_args(pipe_hnd, mem_ctx, argc, argv, DSPRINT_UNPUBLISH);
1426 NTSTATUS rpc_printer_publish_update_internals(struct net_context *c,
1427 const struct dom_sid *domain_sid,
1428 const char *domain_name,
1429 struct cli_state *cli,
1430 struct rpc_pipe_client *pipe_hnd,
1431 TALLOC_CTX *mem_ctx,
1432 int argc,
1433 const char **argv)
1435 return rpc_printer_publish_internals_args(pipe_hnd, mem_ctx, argc, argv, DSPRINT_UPDATE);
1439 * List print-queues w.r.t. their publishing state
1441 * All parameters are provided by the run_rpc_command function, except for
1442 * argc, argv which are passed through.
1444 * @param c A net_context structure
1445 * @param domain_sid The domain sid aquired from the remote server
1446 * @param cli A cli_state connected to the server.
1447 * @param mem_ctx Talloc context, destoyed on compleation of the function.
1448 * @param argc Standard main() style argc
1449 * @param argv Standard main() style argv. Initial components are already
1450 * stripped
1452 * @return Normal NTSTATUS return.
1455 NTSTATUS rpc_printer_publish_list_internals(struct net_context *c,
1456 const struct dom_sid *domain_sid,
1457 const char *domain_name,
1458 struct cli_state *cli,
1459 struct rpc_pipe_client *pipe_hnd,
1460 TALLOC_CTX *mem_ctx,
1461 int argc,
1462 const char **argv)
1464 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
1465 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1466 uint32_t i, num_printers;
1467 uint32_t level = 7;
1468 const char *printername, *sharename;
1469 union spoolss_PrinterInfo *info_enum;
1470 union spoolss_PrinterInfo info;
1471 struct policy_handle hnd = { 0, };
1472 int state;
1473 WERROR werr;
1475 if (!get_printer_info(pipe_hnd, mem_ctx, 2, argc, argv, &num_printers, &info_enum))
1476 return nt_status;
1478 for (i = 0; i < num_printers; i++) {
1480 /* do some initialization */
1481 printername = info_enum[i].info2.printername;
1482 sharename = info_enum[i].info2.sharename;
1484 if (!printername || !sharename) {
1485 goto done;
1488 /* open printer handle */
1489 if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, sharename,
1490 PRINTER_ALL_ACCESS, cli->user_name, &hnd))
1491 goto done;
1493 /* check for existing dst printer */
1494 if (!net_spoolss_getprinter(pipe_hnd, mem_ctx, &hnd, level, &info))
1495 goto done;
1497 if (!info.info7.guid) {
1498 goto done;
1500 state = info.info7.action;
1501 switch (state) {
1502 case DSPRINT_PUBLISH:
1503 printf(_("printer [%s] is published"),
1504 sharename);
1505 if (c->opt_verbose)
1506 printf(_(", guid: %s"),info.info7.guid);
1507 printf("\n");
1508 break;
1509 case DSPRINT_UNPUBLISH:
1510 printf(_("printer [%s] is unpublished\n"),
1511 sharename);
1512 break;
1513 case DSPRINT_UPDATE:
1514 printf(_("printer [%s] is currently updating\n"),
1515 sharename);
1516 break;
1517 default:
1518 printf(_("unknown state: %d\n"), state);
1519 break;
1523 nt_status = NT_STATUS_OK;
1525 done:
1526 if (is_valid_policy_hnd(&hnd)) {
1527 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &werr);
1530 return nt_status;
1534 * Migrate Printer-ACLs from a source server to the destination server
1536 * All parameters are provided by the run_rpc_command function, except for
1537 * argc, argv which are passed through.
1539 * @param c A net_context structure
1540 * @param domain_sid The domain sid aquired from the remote server
1541 * @param cli A cli_state connected to the server.
1542 * @param mem_ctx Talloc context, destoyed on compleation of the function.
1543 * @param argc Standard main() style argc
1544 * @param argv Standard main() style argv. Initial components are already
1545 * stripped
1547 * @return Normal NTSTATUS return.
1550 NTSTATUS rpc_printer_migrate_security_internals(struct net_context *c,
1551 const struct dom_sid *domain_sid,
1552 const char *domain_name,
1553 struct cli_state *cli,
1554 struct rpc_pipe_client *pipe_hnd,
1555 TALLOC_CTX *mem_ctx,
1556 int argc,
1557 const char **argv)
1559 struct dcerpc_binding_handle *b_src = pipe_hnd->binding_handle;
1560 /* TODO: what now, info2 or info3 ?
1561 convince jerry that we should add clientside setacls level 3 at least
1563 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1564 uint32_t i = 0;
1565 uint32_t num_printers;
1566 uint32_t level = 2;
1567 const char *printername, *sharename;
1568 struct rpc_pipe_client *pipe_hnd_dst = NULL;
1569 struct dcerpc_binding_handle *b_dst = NULL;
1570 struct policy_handle hnd_src = { 0, };
1571 struct policy_handle hnd_dst = { 0, };
1572 union spoolss_PrinterInfo *info_enum;
1573 struct cli_state *cli_dst = NULL;
1574 union spoolss_PrinterInfo info_src, info_dst;
1575 WERROR werr;
1577 DEBUG(3,("copying printer ACLs\n"));
1579 /* connect destination PI_SPOOLSS */
1580 nt_status = connect_dst_pipe(c, &cli_dst, &pipe_hnd_dst,
1581 &ndr_table_spoolss);
1582 if (!NT_STATUS_IS_OK(nt_status)) {
1583 return nt_status;
1585 b_dst = pipe_hnd_dst->binding_handle;
1587 /* enum source printers */
1588 if (!get_printer_info(pipe_hnd, mem_ctx, level, argc, argv, &num_printers, &info_enum)) {
1589 nt_status = NT_STATUS_UNSUCCESSFUL;
1590 goto done;
1593 if (!num_printers) {
1594 printf (_("no printers found on server.\n"));
1595 nt_status = NT_STATUS_OK;
1596 goto done;
1599 /* do something for all printers */
1600 for (i = 0; i < num_printers; i++) {
1602 /* do some initialization */
1603 printername = info_enum[i].info2.printername;
1604 sharename = info_enum[i].info2.sharename;
1606 if (!printername || !sharename) {
1607 nt_status = NT_STATUS_UNSUCCESSFUL;
1608 goto done;
1611 /* we can reset NT_STATUS here because we do not
1612 get any real NT_STATUS-codes anymore from now on */
1613 nt_status = NT_STATUS_UNSUCCESSFUL;
1615 d_printf(_("migrating printer ACLs for: [%s] / [%s]\n"),
1616 printername, sharename);
1618 /* according to msdn you have specify these access-rights
1619 to see the security descriptor
1620 - READ_CONTROL (DACL)
1621 - ACCESS_SYSTEM_SECURITY (SACL)
1624 /* open src printer handle */
1625 if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, sharename,
1626 MAXIMUM_ALLOWED_ACCESS, cli->user_name, &hnd_src))
1627 goto done;
1629 /* open dst printer handle */
1630 if (!net_spoolss_open_printer_ex(pipe_hnd_dst, mem_ctx, sharename,
1631 PRINTER_ALL_ACCESS, cli_dst->user_name, &hnd_dst))
1632 goto done;
1634 /* check for existing dst printer */
1635 if (!net_spoolss_getprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, level, &info_dst))
1636 goto done;
1638 /* check for existing src printer */
1639 if (!net_spoolss_getprinter(pipe_hnd, mem_ctx, &hnd_src, 3, &info_src))
1640 goto done;
1642 /* Copy Security Descriptor */
1644 /* copy secdesc (info level 2) */
1645 info_dst.info2.devmode = NULL;
1646 if (info_src.info3.secdesc == NULL) {
1647 info_dst.info2.secdesc = NULL;
1648 } else {
1649 info_dst.info2.secdesc
1650 = security_descriptor_copy(mem_ctx,
1651 info_src.info3.secdesc);
1652 if (info_dst.info2.secdesc == NULL) {
1653 nt_status = NT_STATUS_NO_MEMORY;
1654 goto done;
1658 if (c->opt_verbose)
1659 display_sec_desc(info_dst.info2.secdesc);
1661 if (!net_spoolss_setprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, 2, &info_dst))
1662 goto done;
1664 DEBUGADD(1,("\tSetPrinter of SECDESC succeeded\n"));
1667 /* close printer handles here */
1668 if (is_valid_policy_hnd(&hnd_src)) {
1669 dcerpc_spoolss_ClosePrinter(b_src, mem_ctx, &hnd_src, &werr);
1672 if (is_valid_policy_hnd(&hnd_dst)) {
1673 dcerpc_spoolss_ClosePrinter(b_dst, mem_ctx, &hnd_dst, &werr);
1678 nt_status = NT_STATUS_OK;
1680 done:
1682 if (is_valid_policy_hnd(&hnd_src)) {
1683 dcerpc_spoolss_ClosePrinter(b_src, mem_ctx, &hnd_src, &werr);
1686 if (is_valid_policy_hnd(&hnd_dst)) {
1687 dcerpc_spoolss_ClosePrinter(b_dst, mem_ctx, &hnd_dst, &werr);
1690 if (cli_dst) {
1691 cli_shutdown(cli_dst);
1693 return nt_status;
1697 * Migrate printer-forms from a src server to the dst server
1699 * All parameters are provided by the run_rpc_command function, except for
1700 * argc, argv which are passed through.
1702 * @param c A net_context structure
1703 * @param domain_sid The domain sid aquired from the remote server
1704 * @param cli A cli_state connected to the server.
1705 * @param mem_ctx Talloc context, destoyed on compleation of the function.
1706 * @param argc Standard main() style argc
1707 * @param argv Standard main() style argv. Initial components are already
1708 * stripped
1710 * @return Normal NTSTATUS return.
1713 NTSTATUS rpc_printer_migrate_forms_internals(struct net_context *c,
1714 const struct dom_sid *domain_sid,
1715 const char *domain_name,
1716 struct cli_state *cli,
1717 struct rpc_pipe_client *pipe_hnd,
1718 TALLOC_CTX *mem_ctx,
1719 int argc,
1720 const char **argv)
1722 struct dcerpc_binding_handle *b_src = pipe_hnd->binding_handle;
1723 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1724 WERROR result;
1725 uint32_t i, f;
1726 uint32_t num_printers;
1727 uint32_t level = 1;
1728 const char *printername, *sharename;
1729 struct rpc_pipe_client *pipe_hnd_dst = NULL;
1730 struct dcerpc_binding_handle *b_dst = NULL;
1731 struct policy_handle hnd_src = { 0, };
1732 struct policy_handle hnd_dst = { 0, };
1733 union spoolss_PrinterInfo *info_enum;
1734 union spoolss_PrinterInfo info_dst;
1735 uint32_t num_forms;
1736 union spoolss_FormInfo *forms;
1737 struct cli_state *cli_dst = NULL;
1739 DEBUG(3,("copying forms\n"));
1741 /* connect destination PI_SPOOLSS */
1742 nt_status = connect_dst_pipe(c, &cli_dst, &pipe_hnd_dst,
1743 &ndr_table_spoolss);
1744 if (!NT_STATUS_IS_OK(nt_status)) {
1745 return nt_status;
1747 b_dst = pipe_hnd_dst->binding_handle;
1749 /* enum src printers */
1750 if (!get_printer_info(pipe_hnd, mem_ctx, 2, argc, argv, &num_printers, &info_enum)) {
1751 nt_status = NT_STATUS_UNSUCCESSFUL;
1752 goto done;
1755 if (!num_printers) {
1756 printf (_("no printers found on server.\n"));
1757 nt_status = NT_STATUS_OK;
1758 goto done;
1761 /* do something for all printers */
1762 for (i = 0; i < num_printers; i++) {
1764 /* do some initialization */
1765 printername = info_enum[i].info2.printername;
1766 sharename = info_enum[i].info2.sharename;
1768 if (!printername || !sharename) {
1769 nt_status = NT_STATUS_UNSUCCESSFUL;
1770 goto done;
1772 /* we can reset NT_STATUS here because we do not
1773 get any real NT_STATUS-codes anymore from now on */
1774 nt_status = NT_STATUS_UNSUCCESSFUL;
1776 d_printf(_("migrating printer forms for: [%s] / [%s]\n"),
1777 printername, sharename);
1780 /* open src printer handle */
1781 if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, sharename,
1782 MAXIMUM_ALLOWED_ACCESS, cli->user_name, &hnd_src))
1783 goto done;
1785 /* open dst printer handle */
1786 if (!net_spoolss_open_printer_ex(pipe_hnd_dst, mem_ctx, sharename,
1787 PRINTER_ALL_ACCESS, cli->user_name, &hnd_dst))
1788 goto done;
1790 /* check for existing dst printer */
1791 if (!net_spoolss_getprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, level, &info_dst))
1792 goto done;
1794 /* finally migrate forms */
1795 if (!net_spoolss_enumforms(pipe_hnd, mem_ctx, &hnd_src, level, &num_forms, &forms))
1796 goto done;
1798 DEBUG(1,("got %d forms for printer\n", num_forms));
1801 for (f = 0; f < num_forms; f++) {
1803 struct spoolss_AddFormInfoCtr info_ctr;
1804 NTSTATUS status;
1806 /* only migrate FORM_PRINTER types, according to jerry
1807 FORM_BUILTIN-types are hard-coded in samba */
1808 if (forms[f].info1.flags != SPOOLSS_FORM_PRINTER)
1809 continue;
1811 if (c->opt_verbose)
1812 d_printf(_("\tmigrating form # %d [%s] of type "
1813 "[%d]\n"),
1814 f, forms[f].info1.form_name,
1815 forms[f].info1.flags);
1816 info_ctr.level = 1;
1817 info_ctr.info.info1 = (struct spoolss_AddFormInfo1 *)
1818 (void *)&forms[f].info1;
1820 /* FIXME: there might be something wrong with samba's
1821 builtin-forms */
1822 status = dcerpc_spoolss_AddForm(b_dst, mem_ctx,
1823 &hnd_dst,
1824 &info_ctr,
1825 &result);
1826 if (!NT_STATUS_IS_OK(status)) {
1827 d_printf(_("\tdcerpc_spoolss_AddForm form %d: [%s] - %s\n"),
1828 f, forms[f].info1.form_name, nt_errstr(status));
1829 continue;
1831 if (!W_ERROR_IS_OK(result)) {
1832 d_printf(_("\tAddForm form %d: [%s] refused.\n"),
1833 f, forms[f].info1.form_name);
1834 continue;
1837 DEBUGADD(1,("\tAddForm of [%s] succeeded\n",
1838 forms[f].info1.form_name));
1842 /* close printer handles here */
1843 if (is_valid_policy_hnd(&hnd_src)) {
1844 dcerpc_spoolss_ClosePrinter(b_src, mem_ctx, &hnd_src, &result);
1847 if (is_valid_policy_hnd(&hnd_dst)) {
1848 dcerpc_spoolss_ClosePrinter(b_dst, mem_ctx, &hnd_dst, &result);
1852 nt_status = NT_STATUS_OK;
1854 done:
1856 if (is_valid_policy_hnd(&hnd_src)) {
1857 dcerpc_spoolss_ClosePrinter(b_src, mem_ctx, &hnd_src, &result);
1860 if (is_valid_policy_hnd(&hnd_dst)) {
1861 dcerpc_spoolss_ClosePrinter(b_dst, mem_ctx, &hnd_dst, &result);
1864 if (cli_dst) {
1865 cli_shutdown(cli_dst);
1867 return nt_status;
1871 * Migrate printer-drivers from a src server to the dst server
1873 * All parameters are provided by the run_rpc_command function, except for
1874 * argc, argv which are passed through.
1876 * @param c A net_context structure
1877 * @param domain_sid The domain sid aquired from the remote server
1878 * @param cli A cli_state connected to the server.
1879 * @param mem_ctx Talloc context, destoyed on compleation of the function.
1880 * @param argc Standard main() style argc
1881 * @param argv Standard main() style argv. Initial components are already
1882 * stripped
1884 * @return Normal NTSTATUS return.
1887 NTSTATUS rpc_printer_migrate_drivers_internals(struct net_context *c,
1888 const struct dom_sid *domain_sid,
1889 const char *domain_name,
1890 struct cli_state *cli,
1891 struct rpc_pipe_client *pipe_hnd,
1892 TALLOC_CTX *mem_ctx,
1893 int argc,
1894 const char **argv)
1896 struct dcerpc_binding_handle *b_src = pipe_hnd->binding_handle;
1897 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1898 uint32_t i, p;
1899 uint32_t num_printers;
1900 uint32_t level = 3;
1901 const char *printername, *sharename;
1902 bool got_src_driver_share = false;
1903 bool got_dst_driver_share = false;
1904 struct rpc_pipe_client *pipe_hnd_dst = NULL;
1905 struct dcerpc_binding_handle *b_dst = NULL;
1906 struct policy_handle hnd_src = { 0, };
1907 struct policy_handle hnd_dst = { 0, };
1908 union spoolss_DriverInfo drv_info_src;
1909 union spoolss_PrinterInfo *info_enum;
1910 union spoolss_PrinterInfo info_dst;
1911 struct cli_state *cli_dst = NULL;
1912 struct cli_state *cli_share_src = NULL;
1913 struct cli_state *cli_share_dst = NULL;
1914 const char *drivername = NULL;
1915 WERROR werr;
1917 DEBUG(3,("copying printer-drivers\n"));
1919 nt_status = connect_dst_pipe(c, &cli_dst, &pipe_hnd_dst,
1920 &ndr_table_spoolss);
1921 if (!NT_STATUS_IS_OK(nt_status)) {
1922 return nt_status;
1924 b_dst = pipe_hnd_dst->binding_handle;
1926 /* open print$-share on the src server */
1927 nt_status = connect_to_service(c, &cli_share_src,
1928 smbXcli_conn_remote_sockaddr(cli->conn),
1929 smbXcli_conn_remote_name(cli->conn),
1930 "print$", "A:");
1931 if (!NT_STATUS_IS_OK(nt_status))
1932 goto done;
1934 got_src_driver_share = true;
1937 /* open print$-share on the dst server */
1938 nt_status = connect_to_service(c, &cli_share_dst,
1939 smbXcli_conn_remote_sockaddr(cli_dst->conn),
1940 smbXcli_conn_remote_name(cli_dst->conn),
1941 "print$", "A:");
1942 if (!NT_STATUS_IS_OK(nt_status))
1943 return nt_status;
1945 got_dst_driver_share = true;
1948 /* enum src printers */
1949 if (!get_printer_info(pipe_hnd, mem_ctx, 2, argc, argv, &num_printers, &info_enum)) {
1950 nt_status = NT_STATUS_UNSUCCESSFUL;
1951 goto done;
1954 if (num_printers == 0) {
1955 printf (_("no printers found on server.\n"));
1956 nt_status = NT_STATUS_OK;
1957 goto done;
1961 /* do something for all printers */
1962 for (p = 0; p < num_printers; p++) {
1964 /* do some initialization */
1965 printername = info_enum[p].info2.printername;
1966 sharename = info_enum[p].info2.sharename;
1968 if (!printername || !sharename) {
1969 nt_status = NT_STATUS_UNSUCCESSFUL;
1970 goto done;
1973 /* we can reset NT_STATUS here because we do not
1974 get any real NT_STATUS-codes anymore from now on */
1975 nt_status = NT_STATUS_UNSUCCESSFUL;
1977 d_printf(_("migrating printer driver for: [%s] / [%s]\n"),
1978 printername, sharename);
1980 /* open dst printer handle */
1981 if (!net_spoolss_open_printer_ex(pipe_hnd_dst, mem_ctx, sharename,
1982 PRINTER_ALL_ACCESS, cli->user_name, &hnd_dst))
1983 goto done;
1985 /* check for existing dst printer */
1986 if (!net_spoolss_getprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, 2, &info_dst))
1987 goto done;
1990 /* open src printer handle */
1991 if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, sharename,
1992 MAXIMUM_ALLOWED_ACCESS,
1993 pipe_hnd->auth->user_name,
1994 &hnd_src))
1995 goto done;
1997 /* in a first step call getdriver for each shared printer (per arch)
1998 to get a list of all files that have to be copied */
2000 for (i=0; archi_table[i].long_archi!=NULL; i++) {
2002 /* getdriver src */
2003 if (!net_spoolss_getprinterdriver(pipe_hnd, mem_ctx, &hnd_src,
2004 level, archi_table[i].long_archi,
2005 archi_table[i].version, &drv_info_src))
2006 continue;
2008 drivername = drv_info_src.info3.driver_name;
2010 if (c->opt_verbose)
2011 display_print_driver3(&drv_info_src.info3);
2013 /* check arch dir */
2014 nt_status = check_arch_dir(cli_share_dst, archi_table[i].short_archi);
2015 if (!NT_STATUS_IS_OK(nt_status))
2016 goto done;
2019 /* copy driver-files */
2020 nt_status = copy_print_driver_3(c, mem_ctx, cli_share_src, cli_share_dst,
2021 archi_table[i].short_archi,
2022 &drv_info_src.info3);
2023 if (!NT_STATUS_IS_OK(nt_status))
2024 goto done;
2027 /* adddriver dst */
2028 if (!net_spoolss_addprinterdriver(pipe_hnd_dst, mem_ctx, level, &drv_info_src)) {
2029 nt_status = NT_STATUS_UNSUCCESSFUL;
2030 goto done;
2033 DEBUGADD(1,("Successfully added driver [%s] for printer [%s]\n",
2034 drivername, printername));
2038 if (!drivername || strlen(drivername) == 0) {
2039 DEBUGADD(1,("Did not get driver for printer %s\n",
2040 printername));
2041 goto done;
2044 /* setdriver dst */
2045 info_dst.info2.drivername = drivername;
2047 if (!net_spoolss_setprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, 2, &info_dst)) {
2048 nt_status = NT_STATUS_UNSUCCESSFUL;
2049 goto done;
2052 DEBUGADD(1,("Successfully set driver %s for printer %s\n",
2053 drivername, printername));
2055 /* close dst */
2056 if (is_valid_policy_hnd(&hnd_dst)) {
2057 dcerpc_spoolss_ClosePrinter(b_dst, mem_ctx, &hnd_dst, &werr);
2060 /* close src */
2061 if (is_valid_policy_hnd(&hnd_src)) {
2062 dcerpc_spoolss_ClosePrinter(b_src, mem_ctx, &hnd_src, &werr);
2066 nt_status = NT_STATUS_OK;
2068 done:
2070 if (is_valid_policy_hnd(&hnd_dst)) {
2071 dcerpc_spoolss_ClosePrinter(b_dst, mem_ctx, &hnd_dst, &werr);
2074 /* close src */
2075 if (is_valid_policy_hnd(&hnd_src)) {
2076 dcerpc_spoolss_ClosePrinter(b_src, mem_ctx, &hnd_src, &werr);
2079 if (cli_dst) {
2080 cli_shutdown(cli_dst);
2083 if (got_src_driver_share)
2084 cli_shutdown(cli_share_src);
2086 if (got_dst_driver_share)
2087 cli_shutdown(cli_share_dst);
2089 return nt_status;
2094 * Migrate printer-queues from a src to the dst server
2095 * (requires a working "addprinter command" to be installed for the local smbd)
2097 * All parameters are provided by the run_rpc_command function, except for
2098 * argc, argv which are passed through.
2100 * @param c A net_context structure
2101 * @param domain_sid The domain sid aquired from the remote server
2102 * @param cli A cli_state connected to the server.
2103 * @param mem_ctx Talloc context, destoyed on compleation of the function.
2104 * @param argc Standard main() style argc
2105 * @param argv Standard main() style argv. Initial components are already
2106 * stripped
2108 * @return Normal NTSTATUS return.
2111 NTSTATUS rpc_printer_migrate_printers_internals(struct net_context *c,
2112 const struct dom_sid *domain_sid,
2113 const char *domain_name,
2114 struct cli_state *cli,
2115 struct rpc_pipe_client *pipe_hnd,
2116 TALLOC_CTX *mem_ctx,
2117 int argc,
2118 const char **argv)
2120 struct dcerpc_binding_handle *b_src = pipe_hnd->binding_handle;
2121 WERROR result;
2122 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
2123 uint32_t i = 0, num_printers;
2124 uint32_t level = 2;
2125 union spoolss_PrinterInfo info_dst, info_src;
2126 union spoolss_PrinterInfo *info_enum;
2127 struct cli_state *cli_dst = NULL;
2128 struct policy_handle hnd_src = { 0, };
2129 struct policy_handle hnd_dst = { 0, };
2130 const char *printername, *sharename;
2131 struct rpc_pipe_client *pipe_hnd_dst = NULL;
2132 struct dcerpc_binding_handle *b_dst = NULL;
2133 struct spoolss_SetPrinterInfoCtr info_ctr;
2135 DEBUG(3,("copying printers\n"));
2137 /* connect destination PI_SPOOLSS */
2138 nt_status = connect_dst_pipe(c, &cli_dst, &pipe_hnd_dst,
2139 &ndr_table_spoolss);
2140 if (!NT_STATUS_IS_OK(nt_status)) {
2141 return nt_status;
2143 b_dst = pipe_hnd_dst->binding_handle;
2145 /* enum printers */
2146 if (!get_printer_info(pipe_hnd, mem_ctx, level, argc, argv, &num_printers, &info_enum)) {
2147 nt_status = NT_STATUS_UNSUCCESSFUL;
2148 goto done;
2151 if (!num_printers) {
2152 printf (_("no printers found on server.\n"));
2153 nt_status = NT_STATUS_OK;
2154 goto done;
2157 /* do something for all printers */
2158 for (i = 0; i < num_printers; i++) {
2160 struct spoolss_SetPrinterInfo2 info2;
2162 /* do some initialization */
2163 printername = info_enum[i].info2.printername;
2164 sharename = info_enum[i].info2.sharename;
2166 if (!printername || !sharename) {
2167 nt_status = NT_STATUS_UNSUCCESSFUL;
2168 goto done;
2170 /* we can reset NT_STATUS here because we do not
2171 get any real NT_STATUS-codes anymore from now on */
2172 nt_status = NT_STATUS_UNSUCCESSFUL;
2174 d_printf(_("migrating printer queue for: [%s] / [%s]\n"),
2175 printername, sharename);
2177 /* open dst printer handle */
2178 if (!net_spoolss_open_printer_ex(pipe_hnd_dst, mem_ctx, sharename,
2179 PRINTER_ALL_ACCESS, cli->user_name, &hnd_dst)) {
2181 DEBUG(1,("could not open printer: %s\n", sharename));
2184 /* check for existing dst printer */
2185 if (!net_spoolss_getprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, level, &info_dst)) {
2186 printf (_("could not get printer, creating printer.\n"));
2187 } else {
2188 DEBUG(1,("printer already exists: %s\n", sharename));
2189 /* close printer handle here - dst only, not got src yet. */
2190 if (is_valid_policy_hnd(&hnd_dst)) {
2191 dcerpc_spoolss_ClosePrinter(b_dst, mem_ctx, &hnd_dst, &result);
2193 continue;
2196 /* now get again src printer ctr via getprinter,
2197 we first need a handle for that */
2199 /* open src printer handle */
2200 if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, sharename,
2201 MAXIMUM_ALLOWED_ACCESS, cli->user_name, &hnd_src))
2202 goto done;
2204 /* getprinter on the src server */
2205 if (!net_spoolss_getprinter(pipe_hnd, mem_ctx, &hnd_src, level, &info_src))
2206 goto done;
2208 /* copy each src printer to a dst printer 1:1,
2209 maybe some values have to be changed though */
2210 d_printf(_("creating printer: %s\n"), printername);
2212 info_ctr.level = level;
2213 spoolss_printerinfo2_to_setprinterinfo2(&info_src.info2, &info2);
2214 info_ctr.info.info2 = &info2;
2216 result = rpccli_spoolss_addprinterex(pipe_hnd_dst,
2217 mem_ctx,
2218 &info_ctr);
2220 if (W_ERROR_IS_OK(result))
2221 d_printf (_("printer [%s] successfully added.\n"),
2222 printername);
2223 else if (W_ERROR_V(result) == W_ERROR_V(WERR_PRINTER_ALREADY_EXISTS))
2224 d_fprintf (stderr, _("printer [%s] already exists.\n"),
2225 printername);
2226 else {
2227 d_fprintf (stderr, _("could not create printer [%s]\n"),
2228 printername);
2229 goto done;
2232 /* close printer handles here */
2233 if (is_valid_policy_hnd(&hnd_src)) {
2234 dcerpc_spoolss_ClosePrinter(b_src, mem_ctx, &hnd_src, &result);
2237 if (is_valid_policy_hnd(&hnd_dst)) {
2238 dcerpc_spoolss_ClosePrinter(b_dst, mem_ctx, &hnd_dst, &result);
2242 nt_status = NT_STATUS_OK;
2244 done:
2245 if (is_valid_policy_hnd(&hnd_src)) {
2246 dcerpc_spoolss_ClosePrinter(b_src, mem_ctx, &hnd_src, &result);
2249 if (is_valid_policy_hnd(&hnd_dst)) {
2250 dcerpc_spoolss_ClosePrinter(b_dst, mem_ctx, &hnd_dst, &result);
2253 if (cli_dst) {
2254 cli_shutdown(cli_dst);
2256 return nt_status;
2260 * Migrate Printer-Settings from a src server to the dst server
2261 * (for this to work, printers and drivers already have to be migrated earlier)
2263 * All parameters are provided by the run_rpc_command function, except for
2264 * argc, argv which are passed through.
2266 * @param c A net_context structure
2267 * @param domain_sid The domain sid aquired from the remote server
2268 * @param cli A cli_state connected to the server.
2269 * @param mem_ctx Talloc context, destoyed on compleation of the function.
2270 * @param argc Standard main() style argc
2271 * @param argv Standard main() style argv. Initial components are already
2272 * stripped
2274 * @return Normal NTSTATUS return.
2277 NTSTATUS rpc_printer_migrate_settings_internals(struct net_context *c,
2278 const struct dom_sid *domain_sid,
2279 const char *domain_name,
2280 struct cli_state *cli,
2281 struct rpc_pipe_client *pipe_hnd,
2282 TALLOC_CTX *mem_ctx,
2283 int argc,
2284 const char **argv)
2286 struct dcerpc_binding_handle *b_src = pipe_hnd->binding_handle;
2288 /* FIXME: Here the nightmare begins */
2290 WERROR result;
2291 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
2292 uint32_t i = 0, j = 0;
2293 uint32_t num_printers;
2294 uint32_t level = 2;
2295 const char *printername, *sharename;
2296 struct rpc_pipe_client *pipe_hnd_dst = NULL;
2297 struct dcerpc_binding_handle *b_dst = NULL;
2298 struct policy_handle hnd_src = { 0, };
2299 struct policy_handle hnd_dst = { 0, };
2300 union spoolss_PrinterInfo *info_enum;
2301 union spoolss_PrinterInfo info_dst_publish;
2302 union spoolss_PrinterInfo info_dst;
2303 struct cli_state *cli_dst = NULL;
2304 const char *longname;
2305 const char **keylist = NULL;
2307 /* FIXME GD */
2308 ZERO_STRUCT(info_dst_publish);
2310 DEBUG(3,("copying printer settings\n"));
2312 /* connect destination PI_SPOOLSS */
2313 nt_status = connect_dst_pipe(c, &cli_dst, &pipe_hnd_dst,
2314 &ndr_table_spoolss);
2315 if (!NT_STATUS_IS_OK(nt_status)) {
2316 return nt_status;
2318 b_dst = pipe_hnd_dst->binding_handle;
2320 /* enum src printers */
2321 if (!get_printer_info(pipe_hnd, mem_ctx, level, argc, argv, &num_printers, &info_enum)) {
2322 nt_status = NT_STATUS_UNSUCCESSFUL;
2323 goto done;
2326 if (!num_printers) {
2327 printf (_("no printers found on server.\n"));
2328 nt_status = NT_STATUS_OK;
2329 goto done;
2333 /* needed for dns-strings in regkeys */
2334 longname = get_mydnsfullname();
2335 if (!longname) {
2336 nt_status = NT_STATUS_UNSUCCESSFUL;
2337 goto done;
2340 /* do something for all printers */
2341 for (i = 0; i < num_printers; i++) {
2343 uint32_t value_needed;
2344 uint32_t data_needed;
2345 enum winreg_Type type;
2346 struct spoolss_EnumPrinterData r;
2348 /* do some initialization */
2349 printername = info_enum[i].info2.printername;
2350 sharename = info_enum[i].info2.sharename;
2352 if (!printername || !sharename) {
2353 nt_status = NT_STATUS_UNSUCCESSFUL;
2354 goto done;
2356 /* we can reset NT_STATUS here because we do not
2357 get any real NT_STATUS-codes anymore from now on */
2358 nt_status = NT_STATUS_UNSUCCESSFUL;
2360 d_printf(_("migrating printer settings for: [%s] / [%s]\n"),
2361 printername, sharename);
2364 /* open src printer handle */
2365 if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, sharename,
2366 MAXIMUM_ALLOWED_ACCESS, cli->user_name, &hnd_src))
2367 goto done;
2369 /* open dst printer handle */
2370 if (!net_spoolss_open_printer_ex(pipe_hnd_dst, mem_ctx, sharename,
2371 PRINTER_ALL_ACCESS, cli_dst->user_name, &hnd_dst))
2372 goto done;
2374 /* check for existing dst printer */
2375 if (!net_spoolss_getprinter(pipe_hnd_dst, mem_ctx, &hnd_dst,
2376 level, &info_dst))
2377 goto done;
2380 /* STEP 1: COPY DEVICE-MODE and other
2381 PRINTER_INFO_2-attributes
2384 info_dst.info2 = info_enum[i].info2;
2386 /* why is the port always disconnected when the printer
2387 is correctly installed (incl. driver ???) */
2388 info_dst.info2.portname = SAMBA_PRINTER_PORT_NAME;
2390 /* check if printer is published */
2391 if (info_enum[i].info2.attributes & PRINTER_ATTRIBUTE_PUBLISHED) {
2393 /* check for existing dst printer */
2394 if (!net_spoolss_getprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, 7, &info_dst_publish))
2395 goto done;
2397 info_dst_publish.info7.action = DSPRINT_PUBLISH;
2399 /* ignore false from setprinter due to WERR_IO_PENDING */
2400 net_spoolss_setprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, 7, &info_dst_publish);
2402 DEBUG(3,("republished printer\n"));
2405 if (info_enum[i].info2.devmode != NULL) {
2407 /* copy devmode (info level 2) */
2408 info_dst.info2.devmode = info_enum[i].info2.devmode;
2410 /* do not copy security descriptor (we have another
2411 * command for that) */
2412 info_dst.info2.secdesc = NULL;
2414 #if 0
2415 info_dst.info2.devmode.devicename =
2416 talloc_asprintf(mem_ctx, "\\\\%s\\%s",
2417 longname, printername);
2418 if (!info_dst.info2.devmode.devicename) {
2419 nt_status = NT_STATUS_NO_MEMORY;
2420 goto done;
2422 #endif
2423 if (!net_spoolss_setprinter(pipe_hnd_dst, mem_ctx, &hnd_dst,
2424 level, &info_dst))
2425 goto done;
2427 DEBUGADD(1,("\tSetPrinter of DEVICEMODE succeeded\n"));
2430 /* STEP 2: COPY REGISTRY VALUES */
2432 /* please keep in mind that samba parse_spools gives horribly
2433 crippled results when used to rpccli_spoolss_enumprinterdataex
2434 a win2k3-server. (Bugzilla #1851)
2435 FIXME: IIRC I've seen it too on a win2k-server
2438 r.in.handle = &hnd_src;
2439 r.in.enum_index = 0;
2440 r.in.value_offered = 0;
2441 r.in.data_offered = 0;
2442 r.out.value_name = NULL;
2443 r.out.value_needed = &value_needed;
2444 r.out.type = &type;
2445 r.out.data = NULL;
2446 r.out.data_needed = &data_needed;
2448 /* enumerate data on src handle */
2449 nt_status = dcerpc_spoolss_EnumPrinterData_r(b_src, mem_ctx, &r);
2451 r.in.data_offered = *r.out.data_needed;
2452 r.in.value_offered = *r.out.value_needed;
2453 r.out.data = talloc_zero_array(mem_ctx, uint8_t, r.in.data_offered);
2454 r.out.value_name = talloc_zero_array(mem_ctx, char, r.in.value_offered);
2456 /* loop for all printerdata of "PrinterDriverData" */
2457 while (NT_STATUS_IS_OK(nt_status) && W_ERROR_IS_OK(r.out.result)) {
2459 r.in.enum_index++;
2461 nt_status = dcerpc_spoolss_EnumPrinterData_r(b_src, mem_ctx, &r);
2463 /* loop for all reg_keys */
2464 if (NT_STATUS_IS_OK(nt_status) && W_ERROR_IS_OK(r.out.result)) {
2466 /* display_value */
2467 if (c->opt_verbose) {
2468 struct registry_value v;
2469 v.type = *r.out.type;
2470 v.data = data_blob_const(
2471 r.out.data, r.in.data_offered);
2473 display_reg_value(SPOOL_PRINTERDATA_KEY,
2474 r.out.value_name, &v);
2477 /* set_value */
2478 if (!net_spoolss_setprinterdata(pipe_hnd_dst, mem_ctx,
2479 &hnd_dst, r.out.value_name,
2480 *r.out.type, r.out.data, r.in.data_offered))
2481 goto done;
2483 DEBUGADD(1,("\tSetPrinterData of [%s] succeeded\n",
2484 r.out.value_name));
2488 /* STEP 3: COPY SUBKEY VALUES */
2490 /* here we need to enum all printer_keys and then work
2491 on the result with enum_printer_key_ex. nt4 does not
2492 respond to enumprinterkey, win2k does, so continue
2493 in case of an error */
2495 if (!net_spoolss_enumprinterkey(pipe_hnd, mem_ctx, &hnd_src, "", &keylist)) {
2496 printf(_("got no key-data\n"));
2497 continue;
2501 /* work on a list of printer keys
2502 each key has to be enumerated to get all required
2503 information. information is then set via setprinterdataex-calls */
2505 if (keylist == NULL)
2506 continue;
2508 for (i=0; keylist && keylist[i] != NULL; i++) {
2510 const char *subkey = keylist[i];
2511 uint32_t count;
2512 struct spoolss_PrinterEnumValues *info;
2514 /* enumerate all src subkeys */
2515 if (!net_spoolss_enumprinterdataex(pipe_hnd, mem_ctx, 0,
2516 &hnd_src, subkey,
2517 &count, &info)) {
2518 goto done;
2521 for (j=0; j < count; j++) {
2523 struct registry_value value;
2524 const char *value_name = info[j].value_name;
2525 bool ok;
2527 value.type = REG_SZ;
2529 /* although samba replies with sane data in most cases we
2530 should try to avoid writing wrong registry data */
2532 if (strequal(value_name, SPOOL_REG_PORTNAME)) {
2533 /* although windows uses a multi-sz, we use a sz */
2534 ok = push_reg_sz(mem_ctx, &value.data, SAMBA_PRINTER_PORT_NAME);
2535 if (!ok) {
2536 nt_status = NT_STATUS_NO_MEMORY;
2537 goto done;
2540 else if (strequal(value_name, SPOOL_REG_UNCNAME)) {
2541 char *unc_name;
2542 if (asprintf(&unc_name, "\\\\%s\\%s", longname, sharename) < 0) {
2543 nt_status = NT_STATUS_NO_MEMORY;
2544 goto done;
2546 ok = push_reg_sz(mem_ctx, &value.data, unc_name);
2547 if (!ok) {
2548 nt_status = NT_STATUS_NO_MEMORY;
2549 goto done;
2551 free(unc_name);
2553 else if (strequal(value_name, SPOOL_REG_URL)) {
2554 continue;
2555 #if 0
2556 /* FIXME: should we really do that ??? */
2557 if (asprintf(&url, "http://%s:631/printers/%s", longname, sharename) < 0) {
2558 nt_status = NT_STATUS_NO_MEMORY;
2559 goto done;
2561 push_reg_sz(mem_ctx, NULL, &value.data, url);
2562 free(url);
2563 #endif
2565 else if (strequal(value_name, SPOOL_REG_SERVERNAME)) {
2566 ok = push_reg_sz(mem_ctx, &value.data, longname);
2567 if (!ok) {
2568 nt_status = NT_STATUS_NO_MEMORY;
2569 goto done;
2572 else if (strequal(value_name, SPOOL_REG_SHORTSERVERNAME)) {
2573 ok = push_reg_sz(mem_ctx, &value.data, lp_netbios_name());
2574 if (!ok) {
2575 nt_status = NT_STATUS_NO_MEMORY;
2576 goto done;
2579 else {
2580 value.type = info[j].type;
2581 value.data = *info[j].data;
2584 if (c->opt_verbose) {
2585 display_reg_value(subkey, value_name, &value);
2588 /* here we have to set all subkeys on the dst server */
2589 if (!net_spoolss_setprinterdataex(pipe_hnd_dst, mem_ctx, &hnd_dst,
2590 subkey, value_name, &value))
2592 goto done;
2595 DEBUGADD(1,("\tSetPrinterDataEx of key [%s\\%s] succeeded\n",
2596 subkey, info[j].value_name));
2601 TALLOC_FREE(keylist);
2603 /* close printer handles here */
2604 if (is_valid_policy_hnd(&hnd_src)) {
2605 dcerpc_spoolss_ClosePrinter(b_src, mem_ctx, &hnd_src, &result);
2608 if (is_valid_policy_hnd(&hnd_dst)) {
2609 dcerpc_spoolss_ClosePrinter(b_dst, mem_ctx, &hnd_dst, &result);
2613 nt_status = NT_STATUS_OK;
2615 done:
2616 if (is_valid_policy_hnd(&hnd_src)) {
2617 dcerpc_spoolss_ClosePrinter(b_src, mem_ctx, &hnd_src, &result);
2620 if (is_valid_policy_hnd(&hnd_dst)) {
2621 dcerpc_spoolss_ClosePrinter(b_dst, mem_ctx, &hnd_dst, &result);
2624 if (cli_dst) {
2625 cli_shutdown(cli_dst);
2627 return nt_status;