r8323: * convert RegSetValue() calls immediately beneath the printer
[Samba/gbeck.git] / source / utils / net_rpc_printer.c
blobf1f82a5ceadddf34d06926b60f5333e118dd5f34
1 /*
2 Samba Unix/Linux SMB client library
3 Distributed SMB/CIFS Server Management Utility
4 Copyright (C) 2004 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 2 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, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
20 #include "includes.h"
21 #include "utils/net.h"
23 struct table_node {
24 const char *long_archi;
25 const char *short_archi;
26 int version;
30 /* support itanium as well */
31 static const struct table_node archi_table[]= {
33 {"Windows 4.0", "WIN40", 0 },
34 {"Windows NT x86", "W32X86", 2 },
35 {"Windows NT x86", "W32X86", 3 },
36 {"Windows NT R4000", "W32MIPS", 2 },
37 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
38 {"Windows NT PowerPC", "W32PPC", 2 },
39 {"Windows IA64", "IA64", 3 },
40 {"Windows x64", "x64", 3 },
41 {NULL, "", -1 }
45 /**
46 * The display-functions for Security-Descriptors were taken from rpcclient
48 * They reside here for debugging purpose and should
49 * possibly be removed later on
51 **/
52 /****************************************************************************
53 convert a security permissions into a string
54 ****************************************************************************/
55 char *get_sec_mask_str(uint32 type)
57 static fstring typestr="";
59 typestr[0] = 0;
61 if (type & GENERIC_ALL_ACCESS)
62 fstrcat(typestr, "Generic all access ");
63 if (type & GENERIC_EXECUTE_ACCESS)
64 fstrcat(typestr, "Generic execute access ");
65 if (type & GENERIC_WRITE_ACCESS)
66 fstrcat(typestr, "Generic write access ");
67 if (type & GENERIC_READ_ACCESS)
68 fstrcat(typestr, "Generic read access ");
69 if (type & MAXIMUM_ALLOWED_ACCESS)
70 fstrcat(typestr, "MAXIMUM_ALLOWED_ACCESS ");
71 if (type & SYSTEM_SECURITY_ACCESS)
72 fstrcat(typestr, "SYSTEM_SECURITY_ACCESS ");
73 if (type & SYNCHRONIZE_ACCESS)
74 fstrcat(typestr, "SYNCHRONIZE_ACCESS ");
75 if (type & WRITE_OWNER_ACCESS)
76 fstrcat(typestr, "WRITE_OWNER_ACCESS ");
77 if (type & WRITE_DAC_ACCESS)
78 fstrcat(typestr, "WRITE_DAC_ACCESS ");
79 if (type & READ_CONTROL_ACCESS)
80 fstrcat(typestr, "READ_CONTROL_ACCESS ");
81 if (type & DELETE_ACCESS)
82 fstrcat(typestr, "DELETE_ACCESS ");
84 printf("\t\tSpecific bits: 0x%lx\n", (unsigned long)type&SPECIFIC_RIGHTS_MASK);
86 return typestr;
90 /****************************************************************************
91 display sec_ace structure
92 ****************************************************************************/
93 void display_sec_ace(SEC_ACE *ace)
95 fstring sid_str;
97 printf("\tACE\n\t\ttype: ");
98 switch (ace->type) {
99 case SEC_ACE_TYPE_ACCESS_ALLOWED:
100 printf("ACCESS ALLOWED");
101 break;
102 case SEC_ACE_TYPE_ACCESS_DENIED:
103 printf("ACCESS DENIED");
104 break;
105 case SEC_ACE_TYPE_SYSTEM_AUDIT:
106 printf("SYSTEM AUDIT");
107 break;
108 case SEC_ACE_TYPE_SYSTEM_ALARM:
109 printf("SYSTEM ALARM");
110 break;
111 default:
112 printf("????");
113 break;
115 printf(" (%d) flags: %d\n", ace->type, ace->flags);
116 printf("\t\tPermissions: 0x%x: %s\n", ace->info.mask, get_sec_mask_str(ace->info.mask));
118 sid_to_string(sid_str, &ace->trustee);
119 printf("\t\tSID: %s\n\n", sid_str);
123 /****************************************************************************
124 display sec_acl structure
125 ****************************************************************************/
126 void display_sec_acl(SEC_ACL *sec_acl)
128 int i;
130 printf("\tACL\tNum ACEs:\t%d\trevision:\t%x\n",
131 sec_acl->num_aces, sec_acl->revision);
132 printf("\t---\n");
134 if (sec_acl->size != 0 && sec_acl->num_aces != 0)
135 for (i = 0; i < sec_acl->num_aces; i++)
136 display_sec_ace(&sec_acl->ace[i]);
140 /****************************************************************************
141 display sec_desc structure
142 ****************************************************************************/
143 void display_sec_desc(SEC_DESC *sec)
145 fstring sid_str;
147 if (sec == NULL)
148 return;
150 if (sec->sacl) {
151 printf("SACL\n");
152 display_sec_acl(sec->sacl);
155 if (sec->dacl) {
156 printf("DACL\n");
157 display_sec_acl(sec->dacl);
160 if (sec->owner_sid) {
161 sid_to_string(sid_str, sec->owner_sid);
162 printf("\tOwner SID:\t%s\n", sid_str);
165 if (sec->grp_sid) {
166 sid_to_string(sid_str, sec->grp_sid);
167 printf("\tParent SID:\t%s\n", sid_str);
173 * This display-printdriver-functions was borrowed from rpcclient/cmd_spoolss.c.
174 * It is here for debugging purpose and should be removed later on.
177 /****************************************************************************
178 printer info level 3 display function
179 ****************************************************************************/
180 static void display_print_driver_3(DRIVER_INFO_3 *i1)
182 fstring name = "";
183 fstring architecture = "";
184 fstring driverpath = "";
185 fstring datafile = "";
186 fstring configfile = "";
187 fstring helpfile = "";
188 fstring dependentfiles = "";
189 fstring monitorname = "";
190 fstring defaultdatatype = "";
192 int length=0;
193 BOOL valid = True;
195 if (i1 == NULL)
196 return;
198 rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
199 rpcstr_pull(architecture, i1->architecture.buffer, sizeof(architecture), -1, STR_TERMINATE);
200 rpcstr_pull(driverpath, i1->driverpath.buffer, sizeof(driverpath), -1, STR_TERMINATE);
201 rpcstr_pull(datafile, i1->datafile.buffer, sizeof(datafile), -1, STR_TERMINATE);
202 rpcstr_pull(configfile, i1->configfile.buffer, sizeof(configfile), -1, STR_TERMINATE);
203 rpcstr_pull(helpfile, i1->helpfile.buffer, sizeof(helpfile), -1, STR_TERMINATE);
204 rpcstr_pull(monitorname, i1->monitorname.buffer, sizeof(monitorname), -1, STR_TERMINATE);
205 rpcstr_pull(defaultdatatype, i1->defaultdatatype.buffer, sizeof(defaultdatatype), -1, STR_TERMINATE);
207 d_printf ("Printer Driver Info 3:\n");
208 d_printf ("\tVersion: [%x]\n", i1->version);
209 d_printf ("\tDriver Name: [%s]\n",name);
210 d_printf ("\tArchitecture: [%s]\n", architecture);
211 d_printf ("\tDriver Path: [%s]\n", driverpath);
212 d_printf ("\tDatafile: [%s]\n", datafile);
213 d_printf ("\tConfigfile: [%s]\n", configfile);
214 d_printf ("\tHelpfile: [%s]\n\n", helpfile);
216 while (valid) {
217 rpcstr_pull(dependentfiles, i1->dependentfiles+length, sizeof(dependentfiles), -1, STR_TERMINATE);
219 length+=strlen(dependentfiles)+1;
221 if (strlen(dependentfiles) > 0) {
222 d_printf ("\tDependentfiles: [%s]\n", dependentfiles);
223 } else {
224 valid = False;
228 printf ("\n");
230 d_printf ("\tMonitorname: [%s]\n", monitorname);
231 d_printf ("\tDefaultdatatype: [%s]\n\n", defaultdatatype);
233 return;
237 static void display_reg_value(const char *subkey, REGISTRY_VALUE value)
239 pstring text;
241 switch(value.type) {
242 case REG_DWORD:
243 d_printf("\t[%s:%s]: REG_DWORD: 0x%08x\n", subkey, value.valuename,
244 *((uint32 *) value.data_p));
245 break;
247 case REG_SZ:
248 rpcstr_pull(text, value.data_p, sizeof(text), value.size,
249 STR_TERMINATE);
250 d_printf("\t[%s:%s]: REG_SZ: %s\n", subkey, value.valuename, text);
251 break;
253 case REG_BINARY:
254 d_printf("\t[%s:%s]: REG_BINARY: unknown length value not displayed\n",
255 subkey, value.valuename);
256 break;
258 case REG_MULTI_SZ: {
259 uint16 *curstr = (uint16 *) value.data_p;
260 uint8 *start = value.data_p;
261 d_printf("\t[%s:%s]: REG_MULTI_SZ:\n", subkey, value.valuename);
262 while ((*curstr != 0) &&
263 ((uint8 *) curstr < start + value.size)) {
264 rpcstr_pull(text, curstr, sizeof(text), -1,
265 STR_TERMINATE);
266 d_printf("%s\n", text);
267 curstr += strlen(text) + 1;
270 break;
272 default:
273 d_printf("\t%s: unknown type %d\n", value.valuename, value.type);
280 * Copies ACLs, DOS-attributes and timestamps from one
281 * file or directory from one connected share to another connected share
283 * @param mem_ctx A talloc-context
284 * @param cli_share_src A connected cli_state
285 * @param cli_share_dst A connected cli_state
286 * @param src_file The source file-name
287 * @param dst_file The destination file-name
288 * @param copy_acls Whether to copy acls
289 * @param copy_attrs Whether to copy DOS attributes
290 * @param copy_timestamps Whether to preserve timestamps
291 * @param is_file Whether this file is a file or a dir
293 * @return Normal NTSTATUS return.
294 **/
295 NTSTATUS net_copy_fileattr(TALLOC_CTX *mem_ctx,
296 struct cli_state *cli_share_src,
297 struct cli_state *cli_share_dst,
298 const char *src_name, const char *dst_name,
299 BOOL copy_acls, BOOL copy_attrs,
300 BOOL copy_timestamps, BOOL is_file)
302 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
303 int fnum_src = 0;
304 int fnum_dst = 0;
305 SEC_DESC *sd = NULL;
306 uint16 attr;
307 time_t f_atime, f_ctime, f_mtime;
310 if (!copy_timestamps && !copy_acls && !copy_attrs)
311 return NT_STATUS_OK;
314 /* open file/dir on the originating server */
316 DEBUGADD(3,("opening %s %s on originating server\n",
317 is_file?"file":"dir", src_name));
319 fnum_src = cli_nt_create(cli_share_src, src_name, READ_CONTROL_ACCESS);
320 if (fnum_src == -1) {
321 DEBUGADD(0,("cannot open %s %s on originating server %s\n",
322 is_file?"file":"dir", src_name, cli_errstr(cli_share_src)));
323 nt_status = cli_nt_error(cli_share_src);
324 goto out;
328 if (copy_acls) {
330 /* get the security descriptor */
331 sd = cli_query_secdesc(cli_share_src, fnum_src, mem_ctx);
332 if (!sd) {
333 DEBUG(0,("failed to get security descriptor: %s\n",
334 cli_errstr(cli_share_src)));
335 nt_status = cli_nt_error(cli_share_src);
336 goto out;
339 if (opt_verbose && DEBUGLEVEL >= 3)
340 display_sec_desc(sd);
344 if (copy_attrs || copy_timestamps) {
346 /* get file attributes */
347 if (!cli_getattrE(cli_share_src, fnum_src, &attr, NULL,
348 &f_ctime, &f_atime, &f_mtime)) {
349 DEBUG(0,("failed to get file-attrs: %s\n",
350 cli_errstr(cli_share_src)));
351 nt_status = cli_nt_error(cli_share_src);
352 goto out;
357 /* open the file/dir on the destination server */
359 fnum_dst = cli_nt_create(cli_share_dst, dst_name, WRITE_DAC_ACCESS | WRITE_OWNER_ACCESS);
360 if (fnum_dst == -1) {
361 DEBUG(0,("failed to open %s on the destination server: %s: %s\n",
362 is_file?"file":"dir", dst_name, cli_errstr(cli_share_dst)));
363 nt_status = cli_nt_error(cli_share_dst);
364 goto out;
367 if (copy_timestamps) {
369 /* set timestamps */
370 if (!cli_setattrE(cli_share_dst, fnum_dst, f_ctime, f_atime, f_mtime)) {
371 DEBUG(0,("failed to set file-attrs (timestamps): %s\n",
372 cli_errstr(cli_share_dst)));
373 nt_status = cli_nt_error(cli_share_dst);
374 goto out;
378 if (copy_acls) {
380 /* set acls */
381 if (!cli_set_secdesc(cli_share_dst, fnum_dst, sd)) {
382 DEBUG(0,("could not set secdesc on %s: %s\n",
383 dst_name, cli_errstr(cli_share_dst)));
384 nt_status = cli_nt_error(cli_share_dst);
385 goto out;
389 if (copy_attrs) {
391 /* set attrs */
392 if (!cli_setatr(cli_share_dst, dst_name, attr, 0)) {
393 DEBUG(0,("failed to set file-attrs: %s\n",
394 cli_errstr(cli_share_dst)));
395 nt_status = cli_nt_error(cli_share_dst);
396 goto out;
401 /* closing files */
403 if (!cli_close(cli_share_src, fnum_src)) {
404 d_printf("could not close %s on originating server: %s\n",
405 is_file?"file":"dir", cli_errstr(cli_share_src));
406 nt_status = cli_nt_error(cli_share_src);
407 goto out;
410 if (!cli_close(cli_share_dst, fnum_dst)) {
411 d_printf("could not close %s on destination server: %s\n",
412 is_file?"file":"dir", cli_errstr(cli_share_dst));
413 nt_status = cli_nt_error(cli_share_dst);
414 goto out;
418 nt_status = NT_STATUS_OK;
420 out:
422 /* cleaning up */
423 if (fnum_src)
424 cli_close(cli_share_src, fnum_src);
426 if (fnum_dst)
427 cli_close(cli_share_dst, fnum_dst);
429 return nt_status;
434 * Copy a file or directory from a connected share to another connected share
436 * @param mem_ctx A talloc-context
437 * @param cli_share_src A connected cli_state
438 * @param cli_share_dst A connected cli_state
439 * @param src_file The source file-name
440 * @param dst_file The destination file-name
441 * @param copy_acls Whether to copy acls
442 * @param copy_attrs Whether to copy DOS attributes
443 * @param copy_timestamps Whether to preserve timestamps
444 * @param is_file Whether this file is a file or a dir
446 * @return Normal NTSTATUS return.
447 **/
448 NTSTATUS net_copy_file(TALLOC_CTX *mem_ctx,
449 struct cli_state *cli_share_src,
450 struct cli_state *cli_share_dst,
451 const char *src_name, const char *dst_name,
452 BOOL copy_acls, BOOL copy_attrs,
453 BOOL copy_timestamps, BOOL is_file)
455 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
456 int fnum_src = 0;
457 int fnum_dst = 0;
458 static int io_bufsize = 64512;
459 int read_size = io_bufsize;
460 char *data = NULL;
461 off_t start = 0;
462 off_t nread = 0;
465 if (!src_name || !dst_name)
466 goto out;
468 if (cli_share_src == NULL || cli_share_dst == NULL)
469 goto out;
472 /* open on the originating server */
473 DEBUGADD(3,("opening %s %s on originating server\n",
474 is_file ? "file":"dir", src_name));
475 if (is_file)
476 fnum_src = cli_open(cli_share_src, src_name, O_RDONLY, DENY_NONE);
477 else
478 fnum_src = cli_nt_create(cli_share_src, src_name, READ_CONTROL_ACCESS);
480 if (fnum_src == -1) {
481 DEBUGADD(0,("cannot open %s %s on originating server %s\n",
482 is_file ? "file":"dir",
483 src_name, cli_errstr(cli_share_src)));
484 nt_status = cli_nt_error(cli_share_src);
485 goto out;
489 if (is_file) {
491 /* open file on the destination server */
492 DEBUGADD(3,("opening file %s on destination server\n", dst_name));
493 fnum_dst = cli_open(cli_share_dst, dst_name,
494 O_RDWR|O_CREAT|O_TRUNC, DENY_NONE);
496 if (fnum_dst == -1) {
497 DEBUGADD(1,("cannot create file %s on destination server: %s\n",
498 dst_name, cli_errstr(cli_share_dst)));
499 nt_status = cli_nt_error(cli_share_dst);
500 goto out;
503 /* allocate memory */
504 if (!(data = (char *)SMB_MALLOC(read_size))) {
505 d_printf("malloc fail for size %d\n", read_size);
506 nt_status = NT_STATUS_NO_MEMORY;
507 goto out;
513 if (opt_verbose) {
515 d_printf("copying [\\\\%s\\%s%s] => [\\\\%s\\%s%s] "
516 "%s ACLs and %s DOS Attributes %s\n",
517 cli_share_src->desthost, cli_share_src->share, src_name,
518 cli_share_dst->desthost, cli_share_dst->share, dst_name,
519 copy_acls ? "with" : "without",
520 copy_attrs ? "with" : "without",
521 copy_timestamps ? "(preserving timestamps)" : "" );
525 while (is_file) {
527 /* copying file */
528 int n, ret;
529 n = cli_read(cli_share_src, fnum_src, data, nread + start,
530 read_size);
532 if (n <= 0)
533 break;
535 ret = cli_write(cli_share_dst, fnum_dst, 0, data,
536 nread + start, n);
538 if (n != ret) {
539 d_printf("Error writing file: %s\n",
540 cli_errstr(cli_share_dst));
541 nt_status = cli_nt_error(cli_share_dst);
542 goto out;
545 nread += n;
549 if (!is_file && !cli_chkpath(cli_share_dst, dst_name)) {
551 /* creating dir */
552 DEBUGADD(3,("creating dir %s on the destination server\n",
553 dst_name));
555 if (!cli_mkdir(cli_share_dst, dst_name)) {
556 DEBUG(0,("cannot create directory %s: %s\n",
557 dst_name, cli_errstr(cli_share_dst)));
558 nt_status = NT_STATUS_NO_SUCH_FILE;
561 if (!cli_chkpath(cli_share_dst, dst_name)) {
562 d_printf("cannot check for directory %s: %s\n",
563 dst_name, cli_errstr(cli_share_dst));
564 goto out;
569 /* closing files */
570 if (!cli_close(cli_share_src, fnum_src)) {
571 d_printf("could not close file on originating server: %s\n",
572 cli_errstr(cli_share_src));
573 nt_status = cli_nt_error(cli_share_src);
574 goto out;
577 if (is_file && !cli_close(cli_share_dst, fnum_dst)) {
578 d_printf("could not close file on destination server: %s\n",
579 cli_errstr(cli_share_dst));
580 nt_status = cli_nt_error(cli_share_dst);
581 goto out;
584 /* possibly we have to copy some file-attributes / acls / sd */
585 nt_status = net_copy_fileattr(mem_ctx, cli_share_src, cli_share_dst,
586 src_name, dst_name, copy_acls,
587 copy_attrs, copy_timestamps, is_file);
588 if (!NT_STATUS_IS_OK(nt_status))
589 goto out;
592 nt_status = NT_STATUS_OK;
594 out:
596 /* cleaning up */
597 if (fnum_src)
598 cli_close(cli_share_src, fnum_src);
600 if (fnum_dst)
601 cli_close(cli_share_dst, fnum_dst);
603 SAFE_FREE(data);
605 return nt_status;
610 * Copy a driverfile from on connected share to another connected share
611 * This silently assumes that a driver-file is picked up from
613 * \\src_server\print$\{arch}\{version}\file
615 * and copied to
617 * \\dst_server\print$\{arch}\file
619 * to be added via setdriver-calls later.
620 * @param mem_ctx A talloc-context
621 * @param cli_share_src A cli_state connected to source print$-share
622 * @param cli_share_dst A cli_state connected to destination print$-share
623 * @param file The file-name to be copied
624 * @param short_archi The name of the driver-architecture (short form)
626 * @return Normal NTSTATUS return.
627 **/
628 static NTSTATUS net_copy_driverfile(TALLOC_CTX *mem_ctx,
629 struct cli_state *cli_share_src,
630 struct cli_state *cli_share_dst,
631 char *file, const char *short_archi) {
633 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
634 const char *p;
635 char *src_name;
636 char *dst_name;
637 fstring version;
638 fstring filename;
639 fstring tok;
641 /* scroll through the file until we have the part
642 beyond archi_table.short_archi */
643 p = file;
644 while (next_token(&p, tok, "\\", sizeof(tok))) {
645 if (strequal(tok, short_archi)) {
646 next_token(&p, version, "\\", sizeof(version));
647 next_token(&p, filename, "\\", sizeof(filename));
651 /* build source file name */
652 if (asprintf(&src_name, "\\%s\\%s\\%s", short_archi, version, filename) < 0 )
653 return NT_STATUS_NO_MEMORY;
656 /* create destination file name */
657 if (asprintf(&dst_name, "\\%s\\%s", short_archi, filename) < 0 )
658 return NT_STATUS_NO_MEMORY;
661 /* finally copy the file */
662 nt_status = net_copy_file(mem_ctx, cli_share_src, cli_share_dst,
663 src_name, dst_name, False, False, False, True);
664 if (!NT_STATUS_IS_OK(nt_status))
665 goto out;
667 nt_status = NT_STATUS_OK;
669 out:
670 SAFE_FREE(src_name);
671 SAFE_FREE(dst_name);
673 return nt_status;
678 * Check for existing Architecture directory on a given server
680 * @param cli_share A cli_state connected to a print$-share
681 * @param short_archi The Architecture for the print-driver
683 * @return Normal NTSTATUS return.
685 static NTSTATUS
686 check_arch_dir(struct cli_state *cli_share, const char *short_archi)
689 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
690 char *dir;
692 if (asprintf(&dir, "\\%s", short_archi) < 0) {
693 return NT_STATUS_NO_MEMORY;
696 DEBUG(10,("creating print-driver dir for architecture: %s\n",
697 short_archi));
699 if (!cli_mkdir(cli_share, dir)) {
700 DEBUG(1,("cannot create directory %s: %s\n",
701 dir, cli_errstr(cli_share)));
702 nt_status = NT_STATUS_NO_SUCH_FILE;
705 if (!cli_chkpath(cli_share, dir)) {
706 d_printf("cannot check %s: %s\n",
707 dir, cli_errstr(cli_share));
708 goto out;
711 nt_status = NT_STATUS_OK;
713 out:
714 SAFE_FREE(dir);
715 return nt_status;
720 * Copy a print-driver (level 3) from one connected print$-share to another
721 * connected print$-share
723 * @param mem_ctx A talloc-context
724 * @param cli_share_src A cli_state connected to a print$-share
725 * @param cli_share_dst A cli_state connected to a print$-share
726 * @param short_archi The Architecture for the print-driver
727 * @param i1 The DRIVER_INFO_3-struct
729 * @return Normal NTSTATUS return.
731 static NTSTATUS
732 copy_print_driver_3(TALLOC_CTX *mem_ctx,
733 struct cli_state *cli_share_src,
734 struct cli_state *cli_share_dst,
735 const char *short_archi, DRIVER_INFO_3 *i1)
737 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
738 int length = 0;
739 BOOL valid = True;
741 fstring name = "";
742 fstring driverpath = "";
743 fstring datafile = "";
744 fstring configfile = "";
745 fstring helpfile = "";
746 fstring dependentfiles = "";
748 if (i1 == NULL)
749 return nt_status;
751 rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
752 rpcstr_pull(driverpath, i1->driverpath.buffer, sizeof(driverpath), -1, STR_TERMINATE);
753 rpcstr_pull(datafile, i1->datafile.buffer, sizeof(datafile), -1, STR_TERMINATE);
754 rpcstr_pull(configfile, i1->configfile.buffer, sizeof(configfile), -1, STR_TERMINATE);
755 rpcstr_pull(helpfile, i1->helpfile.buffer, sizeof(helpfile), -1, STR_TERMINATE);
758 if (opt_verbose)
759 d_printf("copying driver: [%s], for architecture: [%s], version: [%d]\n",
760 name, short_archi, i1->version);
762 nt_status = net_copy_driverfile(mem_ctx, cli_share_src, cli_share_dst,
763 driverpath, short_archi);
764 if (!NT_STATUS_IS_OK(nt_status))
765 return nt_status;
767 nt_status = net_copy_driverfile(mem_ctx, cli_share_src, cli_share_dst,
768 datafile, short_archi);
769 if (!NT_STATUS_IS_OK(nt_status))
770 return nt_status;
772 nt_status = net_copy_driverfile(mem_ctx, cli_share_src, cli_share_dst,
773 configfile, short_archi);
774 if (!NT_STATUS_IS_OK(nt_status))
775 return nt_status;
777 nt_status = net_copy_driverfile(mem_ctx, cli_share_src, cli_share_dst,
778 helpfile, short_archi);
779 if (!NT_STATUS_IS_OK(nt_status))
780 return nt_status;
782 while (valid) {
783 rpcstr_pull(dependentfiles, i1->dependentfiles+length, sizeof(dependentfiles), -1, STR_TERMINATE);
784 length+=strlen(dependentfiles)+1;
785 if (strlen(dependentfiles) > 0) {
787 nt_status = net_copy_driverfile(mem_ctx,
788 cli_share_src, cli_share_dst,
789 dependentfiles, short_archi);
790 if (!NT_STATUS_IS_OK(nt_status))
791 return nt_status;
792 } else {
793 valid = False;
797 return NT_STATUS_OK;
802 * net_spoolss-functions
803 * =====================
805 * the net_spoolss-functions aim to simplify spoolss-client-functions
806 * required during the migration-process wrt buffer-sizes, returned
807 * error-codes, etc.
809 * this greatly reduces the complexitiy of the migrate-functions.
813 static BOOL
814 net_spoolss_enum_printers(struct cli_state *cli, TALLOC_CTX *mem_ctx,
815 char *name, uint32 flags, uint32 level,
816 uint32 *num_printers, PRINTER_INFO_CTR *ctr)
819 WERROR result;
820 uint32 needed;
822 /* enum printers */
823 result = cli_spoolss_enum_printers(
824 cli, mem_ctx, 0, &needed, name, flags,
825 level, num_printers, ctr);
827 if (W_ERROR_V(result) == W_ERROR_V(WERR_INSUFFICIENT_BUFFER))
828 result = cli_spoolss_enum_printers(
829 cli, mem_ctx, needed, NULL, name, flags,
830 level, num_printers, ctr);
833 if (!W_ERROR_IS_OK(result)) {
834 printf("cannot enum printers: %s\n", dos_errstr(result));
835 return False;
838 return True;
842 static BOOL
843 net_spoolss_open_printer_ex(struct cli_state *cli, TALLOC_CTX *mem_ctx,
844 const char *printername, uint32 access_required,
845 const char *username, POLICY_HND *hnd)
847 WERROR result;
848 fstring servername, printername2;
850 slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
852 fstrcpy(printername2, servername);
853 fstrcat(printername2, "\\");
854 fstrcat(printername2, printername);
856 DEBUG(10,("connecting to: %s as %s for %s and access: %x\n",
857 servername, username, printername2, access_required));
859 /* open printer */
860 result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername2,
861 "", access_required,
862 servername, username, hnd);
864 /* be more verbose */
865 if (W_ERROR_V(result) == W_ERROR_V(WERR_ACCESS_DENIED)) {
866 d_printf("no access to printer [%s] on [%s] for user [%s] granted\n",
867 printername2, servername, username);
868 return False;
871 if (!W_ERROR_IS_OK(result)) {
872 d_printf("cannot open printer %s on server %s: %s\n",
873 printername2, servername, dos_errstr(result));
874 return False;
877 DEBUG(2,("got printer handle for printer: %s, server: %s\n",
878 printername2, servername));
880 return True;
884 static BOOL
885 net_spoolss_getprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx,
886 POLICY_HND *hnd, uint32 level,
887 PRINTER_INFO_CTR *ctr)
889 WERROR result;
890 uint32 needed;
892 /* getprinter call */
893 result = cli_spoolss_getprinter(cli,
894 mem_ctx, 0, &needed, hnd, level, ctr);
896 if (W_ERROR_V(result) == W_ERROR_V(WERR_INSUFFICIENT_BUFFER))
897 result = cli_spoolss_getprinter(cli,
898 mem_ctx, needed, NULL, hnd, level, ctr);
900 if (!W_ERROR_IS_OK(result)) {
901 printf("cannot get printer-info: %s\n", dos_errstr(result));
902 return False;
905 return True;
909 static BOOL
910 net_spoolss_setprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx,
911 POLICY_HND *hnd, uint32 level,
912 PRINTER_INFO_CTR *ctr)
914 WERROR result;
916 /* setprinter call */
917 result = cli_spoolss_setprinter(cli, mem_ctx, hnd, level, ctr, 0);
919 if (!W_ERROR_IS_OK(result)) {
920 printf("cannot set printer-info: %s\n", dos_errstr(result));
921 return False;
924 return True;
928 static BOOL
929 net_spoolss_setprinterdata(struct cli_state *cli, TALLOC_CTX *mem_ctx,
930 POLICY_HND *hnd, REGISTRY_VALUE *value)
932 WERROR result;
934 /* setprinterdata call */
935 result = cli_spoolss_setprinterdata(cli, mem_ctx, hnd, value);
937 if (!W_ERROR_IS_OK(result)) {
938 printf ("unable to set printerdata: %s\n", dos_errstr(result));
939 return False;
942 return True;
946 static BOOL
947 net_spoolss_enumprinterkey(struct cli_state *cli, TALLOC_CTX *mem_ctx,
948 POLICY_HND *hnd, const char *keyname,
949 uint16 **keylist)
951 WERROR result;
952 uint32 needed, len;
954 /* enumprinterkey call */
955 result = cli_spoolss_enumprinterkey(
956 cli, mem_ctx, 0, &needed, hnd, keyname, NULL, NULL);
958 if (W_ERROR_V(result) == W_ERROR_V(WERR_MORE_DATA))
959 result = cli_spoolss_enumprinterkey(
960 cli, mem_ctx, needed, NULL, hnd, keyname, keylist,
961 &len);
963 if (!W_ERROR_IS_OK(result)) {
964 printf("enumprinterkey failed: %s\n", dos_errstr(result));
965 return False;
968 return True;
972 static BOOL
973 net_spoolss_enumprinterdataex(struct cli_state *cli, TALLOC_CTX *mem_ctx,
974 uint32 offered,
975 POLICY_HND *hnd, const char *keyname,
976 REGVAL_CTR *ctr)
978 WERROR result;
979 uint32 needed;
981 /* enumprinterdataex call */
982 result = cli_spoolss_enumprinterdataex(
983 cli, mem_ctx, 0, &needed, hnd, keyname, ctr);
985 if (W_ERROR_V(result) == W_ERROR_V(WERR_MORE_DATA))
986 result = cli_spoolss_enumprinterdataex(
987 cli, mem_ctx, needed, NULL, hnd, keyname, ctr);
989 if (!W_ERROR_IS_OK(result)) {
990 printf("enumprinterdataex failed: %s\n", dos_errstr(result));
991 return False;
994 return True;
998 static BOOL
999 net_spoolss_setprinterdataex(struct cli_state *cli, TALLOC_CTX *mem_ctx,
1000 POLICY_HND *hnd, char *keyname,
1001 REGISTRY_VALUE *value)
1003 WERROR result;
1005 /* setprinterdataex call */
1006 result = cli_spoolss_setprinterdataex(cli, mem_ctx, hnd,
1007 keyname, value);
1009 if (!W_ERROR_IS_OK(result)) {
1010 printf("could not set printerdataex: %s\n", dos_errstr(result));
1011 return False;
1014 return True;
1018 static BOOL
1019 net_spoolss_enumforms(struct cli_state *cli, TALLOC_CTX *mem_ctx,
1020 POLICY_HND *hnd, int level, uint32 *num_forms,
1021 FORM_1 **forms)
1024 WERROR result;
1025 uint32 needed;
1027 /* enumforms call */
1028 result = cli_spoolss_enumforms(
1029 cli, mem_ctx, 0, &needed, hnd, level, num_forms, forms);
1031 if (W_ERROR_V(result) == W_ERROR_V(WERR_INSUFFICIENT_BUFFER))
1032 result = cli_spoolss_enumforms(
1033 cli, mem_ctx, needed, NULL, hnd, level,
1034 num_forms, forms);
1036 if (!W_ERROR_IS_OK(result)) {
1037 printf("could not enum forms: %s\n", dos_errstr(result));
1038 return False;
1041 return True;
1045 static BOOL
1046 net_spoolss_enumprinterdrivers (struct cli_state *cli, TALLOC_CTX *mem_ctx,
1047 uint32 level, const char *env,
1048 uint32 *num_drivers,
1049 PRINTER_DRIVER_CTR *ctr)
1051 WERROR result;
1052 uint32 needed;
1054 /* enumprinterdrivers call */
1055 result = cli_spoolss_enumprinterdrivers(
1056 cli, mem_ctx, 0, &needed, level,
1057 env, num_drivers, ctr);
1059 if (W_ERROR_V(result) == W_ERROR_V(WERR_INSUFFICIENT_BUFFER))
1060 result = cli_spoolss_enumprinterdrivers(
1061 cli, mem_ctx, needed, NULL, level,
1062 env, num_drivers, ctr);
1064 if (!W_ERROR_IS_OK(result)) {
1065 printf("cannot enum drivers: %s\n", dos_errstr(result));
1066 return False;
1069 return True;
1073 static BOOL
1074 net_spoolss_getprinterdriver(struct cli_state *cli,
1075 TALLOC_CTX *mem_ctx,
1076 POLICY_HND *hnd, uint32 level,
1077 const char *env, int version,
1078 PRINTER_DRIVER_CTR *ctr)
1080 WERROR result;
1081 uint32 needed;
1083 /* getprinterdriver call */
1084 result = cli_spoolss_getprinterdriver(
1085 cli, mem_ctx, 0, &needed, hnd, level,
1086 env, version, ctr);
1088 if (W_ERROR_V(result) == W_ERROR_V(WERR_INSUFFICIENT_BUFFER))
1089 result = cli_spoolss_getprinterdriver(
1090 cli, mem_ctx, needed, NULL, hnd, level,
1091 env, version, ctr);
1093 if (!W_ERROR_IS_OK(result)) {
1094 DEBUG(1,("cannot get driver (for architecture: %s): %s\n",
1095 env, dos_errstr(result)));
1096 if (W_ERROR_V(result) != W_ERROR_V(WERR_UNKNOWN_PRINTER_DRIVER) &&
1097 W_ERROR_V(result) != W_ERROR_V(WERR_INVALID_ENVIRONMENT)) {
1098 printf("cannot get driver: %s\n", dos_errstr(result));
1100 return False;
1103 return True;
1107 static BOOL
1108 net_spoolss_addprinterdriver(struct cli_state *cli,
1109 TALLOC_CTX *mem_ctx, uint32 level,
1110 PRINTER_DRIVER_CTR *ctr)
1112 WERROR result;
1114 /* addprinterdriver call */
1115 result = cli_spoolss_addprinterdriver(cli, mem_ctx, level, ctr);
1117 /* be more verbose */
1118 if (W_ERROR_V(result) == W_ERROR_V(WERR_ACCESS_DENIED)) {
1119 printf("You are not allowed to add drivers\n");
1120 return False;
1122 if (!W_ERROR_IS_OK(result)) {
1123 printf("cannot add driver: %s\n", dos_errstr(result));
1124 return False;
1127 return True;
1131 * abstraction function to get uint32 num_printers and PRINTER_INFO_CTR ctr
1132 * for a single printer or for all printers depending on argc/argv
1134 static BOOL
1135 get_printer_info(struct cli_state *cli, TALLOC_CTX *mem_ctx,
1136 int level, int argc, const char **argv,
1137 uint32 *num_printers, PRINTER_INFO_CTR *ctr)
1140 POLICY_HND hnd;
1142 /* no arguments given, enumerate all printers */
1143 if (argc == 0) {
1145 if (!net_spoolss_enum_printers(cli, mem_ctx, NULL,
1146 PRINTER_ENUM_LOCAL|PRINTER_ENUM_SHARED,
1147 level, num_printers, ctr))
1148 return False;
1150 goto out;
1154 /* argument given, get a single printer by name */
1155 if (!net_spoolss_open_printer_ex(cli, mem_ctx, argv[0],
1156 MAXIMUM_ALLOWED_ACCESS, cli->user_name, &hnd))
1157 return False;
1159 if (!net_spoolss_getprinter(cli, mem_ctx, &hnd, level, ctr)) {
1160 cli_spoolss_close_printer(cli, mem_ctx, &hnd);
1161 return False;
1164 cli_spoolss_close_printer(cli, mem_ctx, &hnd);
1166 *num_printers = 1;
1168 out:
1169 DEBUG(3,("got %d printers\n", *num_printers));
1171 return True;
1176 /**
1177 * List print-queues (including local printers that are not shared)
1179 * All parameters are provided by the run_rpc_command function, except for
1180 * argc, argv which are passed through.
1182 * @param domain_sid The domain sid aquired from the remote server
1183 * @param cli A cli_state connected to the server.
1184 * @param mem_ctx Talloc context, destoyed on compleation of the function.
1185 * @param argc Standard main() style argc
1186 * @param argv Standard main() style argv. Initial components are already
1187 * stripped
1189 * @return Normal NTSTATUS return.
1191 NTSTATUS rpc_printer_list_internals(const DOM_SID *domain_sid, const char *domain_name,
1192 struct cli_state *cli, TALLOC_CTX *mem_ctx,
1193 int argc, const char **argv)
1195 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1196 uint32 i, num_printers;
1197 uint32 level = 2;
1198 pstring printername, sharename;
1199 PRINTER_INFO_CTR ctr;
1201 printf("listing printers\n");
1203 if (!get_printer_info(cli, mem_ctx, level, argc, argv, &num_printers, &ctr))
1204 return nt_status;
1206 for (i = 0; i < num_printers; i++) {
1208 /* do some initialization */
1209 rpcstr_pull(printername, ctr.printers_2[i].printername.buffer,
1210 sizeof(printername), -1, STR_TERMINATE);
1211 rpcstr_pull(sharename, ctr.printers_2[i].sharename.buffer,
1212 sizeof(sharename), -1, STR_TERMINATE);
1214 d_printf("printer %d: %s, shared as: %s\n",
1215 i+1, printername, sharename);
1218 return NT_STATUS_OK;
1222 /**
1223 * List printer-drivers from a server
1225 * All parameters are provided by the run_rpc_command function, except for
1226 * argc, argv which are passed through.
1228 * @param domain_sid The domain sid aquired from the remote server
1229 * @param cli A cli_state connected to the server.
1230 * @param mem_ctx Talloc context, destoyed on compleation of the function.
1231 * @param argc Standard main() style argc
1232 * @param argv Standard main() style argv. Initial components are already
1233 * stripped
1235 * @return Normal NTSTATUS return.
1237 NTSTATUS rpc_printer_driver_list_internals(const DOM_SID *domain_sid, const char *domain_name,
1238 struct cli_state *cli, TALLOC_CTX *mem_ctx,
1239 int argc, const char **argv)
1241 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1242 uint32 i;
1243 uint32 level = 3;
1244 PRINTER_DRIVER_CTR drv_ctr_enum;
1245 int d;
1247 ZERO_STRUCT(drv_ctr_enum);
1250 printf("listing printer-drivers\n");
1252 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1254 uint32 num_drivers;
1256 /* enum remote drivers */
1257 if (!net_spoolss_enumprinterdrivers(cli, mem_ctx, level,
1258 archi_table[i].long_archi,
1259 &num_drivers, &drv_ctr_enum)) {
1261 nt_status = NT_STATUS_UNSUCCESSFUL;
1262 goto done;
1265 if (num_drivers == 0) {
1266 d_printf ("no drivers found on server for architecture: [%s].\n",
1267 archi_table[i].long_archi);
1268 continue;
1271 d_printf("got %d printer-drivers for architecture: [%s]\n",
1272 num_drivers, archi_table[i].long_archi);
1275 /* do something for all drivers for architecture */
1276 for (d = 0; d < num_drivers; d++) {
1277 display_print_driver_3(&(drv_ctr_enum.info3[d]));
1281 nt_status = NT_STATUS_OK;
1283 done:
1284 return nt_status;
1288 /**
1289 * Publish print-queues with args-wrapper
1291 * @param cli A cli_state connected to the server.
1292 * @param mem_ctx Talloc context, destoyed on compleation of the function.
1293 * @param argc Standard main() style argc
1294 * @param argv Standard main() style argv. Initial components are already
1295 * stripped
1296 * @param action
1298 * @return Normal NTSTATUS return.
1301 static NTSTATUS rpc_printer_publish_internals_args(struct cli_state *cli, TALLOC_CTX *mem_ctx,
1302 int argc, const char **argv, uint32 action)
1304 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1305 uint32 i, num_printers;
1306 uint32 level = 7;
1307 pstring printername, sharename;
1308 PRINTER_INFO_CTR ctr, ctr_pub;
1309 POLICY_HND hnd;
1310 BOOL got_hnd = False;
1311 WERROR result;
1312 const char *action_str;
1314 if (!get_printer_info(cli, mem_ctx, 2, argc, argv, &num_printers, &ctr))
1315 return nt_status;
1317 for (i = 0; i < num_printers; i++) {
1319 /* do some initialization */
1320 rpcstr_pull(printername, ctr.printers_2[i].printername.buffer,
1321 sizeof(printername), -1, STR_TERMINATE);
1322 rpcstr_pull(sharename, ctr.printers_2[i].sharename.buffer,
1323 sizeof(sharename), -1, STR_TERMINATE);
1325 /* open printer handle */
1326 if (!net_spoolss_open_printer_ex(cli, mem_ctx, sharename,
1327 PRINTER_ALL_ACCESS, cli->user_name, &hnd))
1328 goto done;
1330 got_hnd = True;
1332 /* check for existing dst printer */
1333 if (!net_spoolss_getprinter(cli, mem_ctx, &hnd, level, &ctr_pub))
1334 goto done;
1336 /* check action and set string */
1337 switch (action) {
1338 case SPOOL_DS_PUBLISH:
1339 action_str = "published";
1340 break;
1341 case SPOOL_DS_UPDATE:
1342 action_str = "updated";
1343 break;
1344 case SPOOL_DS_UNPUBLISH:
1345 action_str = "unpublished";
1346 break;
1347 default:
1348 action_str = "unknown action";
1349 printf("unkown action: %d\n", action);
1350 break;
1353 ctr_pub.printers_7->action = action;
1355 result = cli_spoolss_setprinter(cli, mem_ctx, &hnd, level, &ctr_pub, 0);
1356 if (!W_ERROR_IS_OK(result) && (W_ERROR_V(result) =! W_ERROR_V(WERR_IO_PENDING))) {
1357 printf("cannot set printer-info: %s\n", dos_errstr(result));
1358 goto done;
1361 printf("successfully %s printer %s in Active Directory\n", action_str, sharename);
1364 nt_status = NT_STATUS_OK;
1366 done:
1367 if (got_hnd)
1368 cli_spoolss_close_printer(cli, mem_ctx, &hnd);
1370 return nt_status;
1373 NTSTATUS rpc_printer_publish_publish_internals(const DOM_SID *domain_sid, const char *domain_name,
1374 struct cli_state *cli, TALLOC_CTX *mem_ctx,
1375 int argc, const char **argv)
1377 return rpc_printer_publish_internals_args(cli, mem_ctx, argc, argv, SPOOL_DS_PUBLISH);
1380 NTSTATUS rpc_printer_publish_unpublish_internals(const DOM_SID *domain_sid, const char *domain_name,
1381 struct cli_state *cli, TALLOC_CTX *mem_ctx,
1382 int argc, const char **argv)
1384 return rpc_printer_publish_internals_args(cli, mem_ctx, argc, argv, SPOOL_DS_UNPUBLISH);
1387 NTSTATUS rpc_printer_publish_update_internals(const DOM_SID *domain_sid, const char *domain_name,
1388 struct cli_state *cli, TALLOC_CTX *mem_ctx,
1389 int argc, const char **argv)
1391 return rpc_printer_publish_internals_args(cli, mem_ctx, argc, argv, SPOOL_DS_UPDATE);
1394 /**
1395 * List print-queues w.r.t. their publishing state
1397 * All parameters are provided by the run_rpc_command function, except for
1398 * argc, argv which are passed through.
1400 * @param domain_sid The domain sid aquired from the remote server
1401 * @param cli A cli_state connected to the server.
1402 * @param mem_ctx Talloc context, destoyed on compleation of the function.
1403 * @param argc Standard main() style argc
1404 * @param argv Standard main() style argv. Initial components are already
1405 * stripped
1407 * @return Normal NTSTATUS return.
1409 NTSTATUS rpc_printer_publish_list_internals(const DOM_SID *domain_sid, const char *domain_name,
1410 struct cli_state *cli, TALLOC_CTX *mem_ctx,
1411 int argc, const char **argv)
1413 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1414 uint32 i, num_printers;
1415 uint32 level = 7;
1416 pstring printername, sharename;
1417 pstring guid;
1418 PRINTER_INFO_CTR ctr, ctr_pub;
1419 POLICY_HND hnd;
1420 BOOL got_hnd = False;
1421 int state;
1423 if (!get_printer_info(cli, mem_ctx, 2, argc, argv, &num_printers, &ctr))
1424 return nt_status;
1426 for (i = 0; i < num_printers; i++) {
1428 ZERO_STRUCT(ctr_pub);
1430 /* do some initialization */
1431 rpcstr_pull(printername, ctr.printers_2[i].printername.buffer,
1432 sizeof(printername), -1, STR_TERMINATE);
1433 rpcstr_pull(sharename, ctr.printers_2[i].sharename.buffer,
1434 sizeof(sharename), -1, STR_TERMINATE);
1436 /* open printer handle */
1437 if (!net_spoolss_open_printer_ex(cli, mem_ctx, sharename,
1438 PRINTER_ALL_ACCESS, cli->user_name, &hnd))
1439 goto done;
1441 got_hnd = True;
1443 /* check for existing dst printer */
1444 if (!net_spoolss_getprinter(cli, mem_ctx, &hnd, level, &ctr_pub))
1445 goto done;
1447 rpcstr_pull(guid, ctr_pub.printers_7->guid.buffer, sizeof(guid), -1, STR_TERMINATE);
1449 state = ctr_pub.printers_7->action;
1450 switch (state) {
1451 case SPOOL_DS_PUBLISH:
1452 printf("printer [%s] is published", sharename);
1453 if (opt_verbose)
1454 printf(", guid: %s", guid);
1455 printf("\n");
1456 break;
1457 case SPOOL_DS_UNPUBLISH:
1458 printf("printer [%s] is unpublished\n", sharename);
1459 break;
1460 case SPOOL_DS_UPDATE:
1461 printf("printer [%s] is currently updating\n", sharename);
1462 break;
1463 default:
1464 printf("unkown state: %d\n", state);
1465 break;
1469 nt_status = NT_STATUS_OK;
1471 done:
1472 if (got_hnd)
1473 cli_spoolss_close_printer(cli, mem_ctx, &hnd);
1475 return nt_status;
1478 /**
1479 * Migrate Printer-ACLs from a source server to the destination server
1481 * All parameters are provided by the run_rpc_command function, except for
1482 * argc, argv which are passed through.
1484 * @param domain_sid The domain sid aquired from the remote server
1485 * @param cli A cli_state connected to the server.
1486 * @param mem_ctx Talloc context, destoyed on compleation of the function.
1487 * @param argc Standard main() style argc
1488 * @param argv Standard main() style argv. Initial components are already
1489 * stripped
1491 * @return Normal NTSTATUS return.
1493 NTSTATUS rpc_printer_migrate_security_internals(const DOM_SID *domain_sid, const char *domain_name,
1494 struct cli_state *cli, TALLOC_CTX *mem_ctx,
1495 int argc, const char **argv)
1497 /* TODO: what now, info2 or info3 ?
1498 convince jerry that we should add clientside setacls level 3 at least
1500 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1501 uint32 i = 0;
1502 uint32 num_printers;
1503 uint32 level = 2;
1504 pstring printername = "", sharename = "";
1505 BOOL got_hnd_src = False;
1506 BOOL got_hnd_dst = False;
1507 BOOL got_dst_spoolss_pipe = False;
1508 POLICY_HND hnd_src, hnd_dst;
1509 PRINTER_INFO_CTR ctr_src, ctr_dst, ctr_enum;
1510 struct cli_state *cli_dst = NULL;
1512 ZERO_STRUCT(ctr_src);
1514 DEBUG(3,("copying printer ACLs\n"));
1516 /* connect destination PI_SPOOLSS */
1517 nt_status = connect_pipe(&cli_dst, PI_SPOOLSS, &got_dst_spoolss_pipe);
1518 if (!NT_STATUS_IS_OK(nt_status))
1519 return nt_status;
1522 /* enum source printers */
1523 if (!get_printer_info(cli, mem_ctx, level, argc, argv, &num_printers, &ctr_enum)) {
1524 nt_status = NT_STATUS_UNSUCCESSFUL;
1525 goto done;
1528 if (!num_printers) {
1529 printf ("no printers found on server.\n");
1530 nt_status = NT_STATUS_OK;
1531 goto done;
1535 /* do something for all printers */
1536 for (i = 0; i < num_printers; i++) {
1538 /* do some initialization */
1539 rpcstr_pull(printername, ctr_enum.printers_2[i].printername.buffer,
1540 sizeof(printername), -1, STR_TERMINATE);
1541 rpcstr_pull(sharename, ctr_enum.printers_2[i].sharename.buffer,
1542 sizeof(sharename), -1, STR_TERMINATE);
1543 /* we can reset NT_STATUS here because we do not
1544 get any real NT_STATUS-codes anymore from now on */
1545 nt_status = NT_STATUS_UNSUCCESSFUL;
1547 d_printf("migrating printer ACLs for: [%s] / [%s]\n",
1548 printername, sharename);
1550 /* according to msdn you have specify these access-rights
1551 to see the security descriptor
1552 - READ_CONTROL (DACL)
1553 - ACCESS_SYSTEM_SECURITY (SACL)
1556 /* open src printer handle */
1557 if (!net_spoolss_open_printer_ex(cli, mem_ctx, sharename,
1558 MAXIMUM_ALLOWED_ACCESS, cli->user_name, &hnd_src))
1559 goto done;
1561 got_hnd_src = True;
1564 /* open dst printer handle */
1565 if (!net_spoolss_open_printer_ex(cli_dst, mem_ctx, sharename,
1566 PRINTER_ALL_ACCESS, cli_dst->user_name, &hnd_dst))
1567 goto done;
1569 got_hnd_dst = True;
1572 /* check for existing dst printer */
1573 if (!net_spoolss_getprinter(cli_dst, mem_ctx, &hnd_dst, level, &ctr_dst))
1574 goto done;
1576 /* check for existing src printer */
1577 if (!net_spoolss_getprinter(cli, mem_ctx, &hnd_src, 3, &ctr_src))
1578 goto done;
1581 /* Copy Security Descriptor */
1583 /* copy secdesc (info level 2) */
1584 ctr_dst.printers_2->devmode = NULL;
1585 ctr_dst.printers_2->secdesc = dup_sec_desc(mem_ctx, ctr_src.printers_3->secdesc);
1587 if (opt_verbose)
1588 display_sec_desc(ctr_dst.printers_2->secdesc);
1590 if (!net_spoolss_setprinter(cli_dst, mem_ctx, &hnd_dst, 2, &ctr_dst))
1591 goto done;
1593 DEBUGADD(1,("\tSetPrinter of SECDESC succeeded\n"));
1596 /* close printer handles here */
1597 if (got_hnd_src) {
1598 cli_spoolss_close_printer(cli, mem_ctx, &hnd_src);
1599 got_hnd_src = False;
1602 if (got_hnd_dst) {
1603 cli_spoolss_close_printer(cli_dst, mem_ctx, &hnd_dst);
1604 got_hnd_dst = False;
1609 nt_status = NT_STATUS_OK;
1611 done:
1613 if (got_hnd_src)
1614 cli_spoolss_close_printer(cli, mem_ctx, &hnd_src);
1616 if (got_hnd_dst)
1617 cli_spoolss_close_printer(cli_dst, mem_ctx, &hnd_dst);
1619 if (got_dst_spoolss_pipe) {
1620 cli_nt_session_close(cli_dst);
1621 cli_shutdown(cli_dst);
1623 return nt_status;
1627 /**
1628 * Migrate printer-forms from a src server to the dst server
1630 * All parameters are provided by the run_rpc_command function, except for
1631 * argc, argv which are passed through.
1633 * @param domain_sid The domain sid aquired from the remote server
1634 * @param cli A cli_state connected to the server.
1635 * @param mem_ctx Talloc context, destoyed on compleation of the function.
1636 * @param argc Standard main() style argc
1637 * @param argv Standard main() style argv. Initial components are already
1638 * stripped
1640 * @return Normal NTSTATUS return.
1642 NTSTATUS rpc_printer_migrate_forms_internals(const DOM_SID *domain_sid, const char *domain_name,
1643 struct cli_state *cli, TALLOC_CTX *mem_ctx,
1644 int argc, const char **argv)
1646 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1647 WERROR result;
1648 uint32 i, f;
1649 uint32 num_printers;
1650 uint32 level = 1;
1651 pstring printername = "", sharename = "";
1652 BOOL got_hnd_src = False;
1653 BOOL got_hnd_dst = False;
1654 BOOL got_dst_spoolss_pipe = False;
1655 POLICY_HND hnd_src, hnd_dst;
1656 PRINTER_INFO_CTR ctr_enum, ctr_dst;
1657 uint32 num_forms;
1658 FORM_1 *forms;
1659 struct cli_state *cli_dst = NULL;
1661 ZERO_STRUCT(ctr_enum);
1663 DEBUG(3,("copying forms\n"));
1665 /* connect destination PI_SPOOLSS */
1666 nt_status = connect_pipe(&cli_dst, PI_SPOOLSS, &got_dst_spoolss_pipe);
1667 if (!NT_STATUS_IS_OK(nt_status))
1668 return nt_status;
1671 /* enum src printers */
1672 if (!get_printer_info(cli, mem_ctx, 2, argc, argv, &num_printers, &ctr_enum)) {
1673 nt_status = NT_STATUS_UNSUCCESSFUL;
1674 goto done;
1677 if (!num_printers) {
1678 printf ("no printers found on server.\n");
1679 nt_status = NT_STATUS_OK;
1680 goto done;
1684 /* do something for all printers */
1685 for (i = 0; i < num_printers; i++) {
1687 /* do some initialization */
1688 rpcstr_pull(printername, ctr_enum.printers_2[i].printername.buffer,
1689 sizeof(printername), -1, STR_TERMINATE);
1690 rpcstr_pull(sharename, ctr_enum.printers_2[i].sharename.buffer,
1691 sizeof(sharename), -1, STR_TERMINATE);
1692 /* we can reset NT_STATUS here because we do not
1693 get any real NT_STATUS-codes anymore from now on */
1694 nt_status = NT_STATUS_UNSUCCESSFUL;
1696 d_printf("migrating printer forms for: [%s] / [%s]\n",
1697 printername, sharename);
1700 /* open src printer handle */
1701 if (!net_spoolss_open_printer_ex(cli, mem_ctx, sharename,
1702 MAXIMUM_ALLOWED_ACCESS, cli->user_name, &hnd_src))
1703 goto done;
1705 got_hnd_src = True;
1708 /* open dst printer handle */
1709 if (!net_spoolss_open_printer_ex(cli_dst, mem_ctx, sharename,
1710 PRINTER_ALL_ACCESS, cli->user_name, &hnd_dst))
1711 goto done;
1713 got_hnd_dst = True;
1716 /* check for existing dst printer */
1717 if (!net_spoolss_getprinter(cli_dst, mem_ctx, &hnd_dst, level, &ctr_dst))
1718 goto done;
1720 /* finally migrate forms */
1721 if (!net_spoolss_enumforms(cli, mem_ctx, &hnd_src, level, &num_forms, &forms))
1722 goto done;
1724 DEBUG(1,("got %d forms for printer\n", num_forms));
1727 for (f = 0; f < num_forms; f++) {
1729 FORM form;
1730 fstring form_name;
1732 /* only migrate FORM_PRINTER types, according to jerry
1733 FORM_BUILTIN-types are hard-coded in samba */
1734 if (forms[f].flag != FORM_PRINTER)
1735 continue;
1737 if (forms[f].name.buffer)
1738 rpcstr_pull(form_name, forms[f].name.buffer,
1739 sizeof(form_name), -1, STR_TERMINATE);
1741 if (opt_verbose)
1742 d_printf("\tmigrating form # %d [%s] of type [%d]\n",
1743 f, form_name, forms[f].flag);
1745 /* is there a more elegant way to do that ? */
1746 form.flags = FORM_PRINTER;
1747 form.size_x = forms[f].width;
1748 form.size_y = forms[f].length;
1749 form.left = forms[f].left;
1750 form.top = forms[f].top;
1751 form.right = forms[f].right;
1752 form.bottom = forms[f].bottom;
1754 init_unistr2(&form.name, form_name, UNI_STR_TERMINATE);
1756 /* FIXME: there might be something wrong with samba's
1757 builtin-forms */
1758 result = cli_spoolss_addform(cli_dst, mem_ctx,
1759 &hnd_dst, 1, &form);
1760 if (!W_ERROR_IS_OK(result)) {
1761 d_printf("\tAddForm form %d: [%s] refused.\n",
1762 f, form_name);
1763 continue;
1766 DEBUGADD(1,("\tAddForm of [%s] succeeded\n", form_name));
1770 /* close printer handles here */
1771 if (got_hnd_src) {
1772 cli_spoolss_close_printer(cli, mem_ctx, &hnd_src);
1773 got_hnd_src = False;
1776 if (got_hnd_dst) {
1777 cli_spoolss_close_printer(cli_dst, mem_ctx, &hnd_dst);
1778 got_hnd_dst = False;
1782 nt_status = NT_STATUS_OK;
1784 done:
1786 if (got_hnd_src)
1787 cli_spoolss_close_printer(cli, mem_ctx, &hnd_src);
1789 if (got_hnd_dst)
1790 cli_spoolss_close_printer(cli_dst, mem_ctx, &hnd_dst);
1792 if (got_dst_spoolss_pipe) {
1793 cli_nt_session_close(cli_dst);
1794 cli_shutdown(cli_dst);
1796 return nt_status;
1801 /**
1802 * Migrate printer-drivers from a src server to the dst server
1804 * All parameters are provided by the run_rpc_command function, except for
1805 * argc, argv which are passed through.
1807 * @param domain_sid The domain sid aquired from the remote server
1808 * @param cli A cli_state connected to the server.
1809 * @param mem_ctx Talloc context, destoyed on compleation of the function.
1810 * @param argc Standard main() style argc
1811 * @param argv Standard main() style argv. Initial components are already
1812 * stripped
1814 * @return Normal NTSTATUS return.
1816 NTSTATUS rpc_printer_migrate_drivers_internals(const DOM_SID *domain_sid, const char *domain_name,
1817 struct cli_state *cli, TALLOC_CTX *mem_ctx,
1818 int argc, const char **argv)
1820 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1821 uint32 i, p;
1822 uint32 num_printers;
1823 uint32 level = 3;
1824 pstring printername = "", sharename = "";
1825 BOOL got_hnd_src = False;
1826 BOOL got_hnd_dst = False;
1827 BOOL got_dst_spoolss_pipe = False;
1828 BOOL got_src_driver_share = False;
1829 BOOL got_dst_driver_share = False;
1830 POLICY_HND hnd_src, hnd_dst;
1831 PRINTER_DRIVER_CTR drv_ctr_src, drv_ctr_dst;
1832 PRINTER_INFO_CTR info_ctr_enum, info_ctr_dst;
1833 struct cli_state *cli_dst = NULL;
1834 struct cli_state *cli_share_src = NULL;
1835 struct cli_state *cli_share_dst = NULL;
1836 fstring drivername = "";
1838 ZERO_STRUCT(drv_ctr_src);
1839 ZERO_STRUCT(drv_ctr_dst);
1840 ZERO_STRUCT(info_ctr_enum);
1841 ZERO_STRUCT(info_ctr_dst);
1844 DEBUG(3,("copying printer-drivers\n"));
1846 nt_status = connect_pipe(&cli_dst, PI_SPOOLSS, &got_dst_spoolss_pipe);
1847 if (!NT_STATUS_IS_OK(nt_status))
1848 return nt_status;
1851 /* open print$-share on the src server */
1852 nt_status = connect_to_service(&cli_share_src, &cli->dest_ip,
1853 cli->desthost, "print$", "A:");
1854 if (!NT_STATUS_IS_OK(nt_status))
1855 return nt_status;
1857 got_src_driver_share = True;
1860 /* open print$-share on the dst server */
1861 nt_status = connect_to_service(&cli_share_dst, &cli_dst->dest_ip,
1862 cli_dst->desthost, "print$", "A:");
1863 if (!NT_STATUS_IS_OK(nt_status))
1864 return nt_status;
1866 got_dst_driver_share = True;
1869 /* enum src printers */
1870 if (!get_printer_info(cli, mem_ctx, 2, argc, argv, &num_printers, &info_ctr_enum)) {
1871 nt_status = NT_STATUS_UNSUCCESSFUL;
1872 goto done;
1875 if (!num_printers) {
1876 printf ("no printers found on server.\n");
1877 nt_status = NT_STATUS_OK;
1878 goto done;
1882 /* do something for all printers */
1883 for (p = 0; p < num_printers; p++) {
1885 /* do some initialization */
1886 rpcstr_pull(printername, info_ctr_enum.printers_2[p].printername.buffer,
1887 sizeof(printername), -1, STR_TERMINATE);
1888 rpcstr_pull(sharename, info_ctr_enum.printers_2[p].sharename.buffer,
1889 sizeof(sharename), -1, STR_TERMINATE);
1890 /* we can reset NT_STATUS here because we do not
1891 get any real NT_STATUS-codes anymore from now on */
1892 nt_status = NT_STATUS_UNSUCCESSFUL;
1894 d_printf("migrating printer driver for: [%s] / [%s]\n",
1895 printername, sharename);
1897 /* open dst printer handle */
1898 if (!net_spoolss_open_printer_ex(cli_dst, mem_ctx, sharename,
1899 PRINTER_ALL_ACCESS, cli->user_name, &hnd_dst))
1900 goto done;
1902 got_hnd_dst = True;
1904 /* check for existing dst printer */
1905 if (!net_spoolss_getprinter(cli_dst, mem_ctx, &hnd_dst, 2, &info_ctr_dst))
1906 goto done;
1909 /* open src printer handle */
1910 if (!net_spoolss_open_printer_ex(cli, mem_ctx, sharename,
1911 MAXIMUM_ALLOWED_ACCESS, cli->user_name, &hnd_src))
1912 goto done;
1914 got_hnd_src = True;
1917 /* in a first step call getdriver for each shared printer (per arch)
1918 to get a list of all files that have to be copied */
1920 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1922 /* getdriver src */
1923 if (!net_spoolss_getprinterdriver(cli, mem_ctx, &hnd_src,
1924 level, archi_table[i].long_archi,
1925 archi_table[i].version, &drv_ctr_src))
1926 continue;
1928 rpcstr_pull(drivername, drv_ctr_src.info3->name.buffer,
1929 sizeof(drivername), -1, STR_TERMINATE);
1931 if (opt_verbose)
1932 display_print_driver_3(drv_ctr_src.info3);
1935 /* check arch dir */
1936 nt_status = check_arch_dir(cli_share_dst, archi_table[i].short_archi);
1937 if (!NT_STATUS_IS_OK(nt_status))
1938 goto done;
1941 /* copy driver-files */
1942 nt_status = copy_print_driver_3(mem_ctx, cli_share_src, cli_share_dst,
1943 archi_table[i].short_archi,
1944 drv_ctr_src.info3);
1945 if (!NT_STATUS_IS_OK(nt_status))
1946 goto done;
1949 /* adddriver dst */
1950 if (!net_spoolss_addprinterdriver(cli_dst, mem_ctx, level, &drv_ctr_src)) {
1951 nt_status = NT_STATUS_UNSUCCESSFUL;
1952 goto done;
1955 DEBUGADD(1,("Sucessfully added driver [%s] for printer [%s]\n",
1956 drivername, printername));
1960 if (strlen(drivername) == 0) {
1961 DEBUGADD(1,("Did not get driver for printer %s\n",
1962 printername));
1963 goto done;
1966 /* setdriver dst */
1967 init_unistr(&info_ctr_dst.printers_2->drivername, drivername);
1969 if (!net_spoolss_setprinter(cli_dst, mem_ctx, &hnd_dst, 2, &info_ctr_dst)) {
1970 nt_status = NT_STATUS_UNSUCCESSFUL;
1971 goto done;
1974 DEBUGADD(1,("Sucessfully set driver %s for printer %s\n",
1975 drivername, printername));
1977 /* close dst */
1978 if (got_hnd_dst) {
1979 cli_spoolss_close_printer(cli_dst, mem_ctx, &hnd_dst);
1980 got_hnd_dst = False;
1983 /* close src */
1984 if (got_hnd_src) {
1985 cli_spoolss_close_printer(cli, mem_ctx, &hnd_src);
1986 got_hnd_src = False;
1990 nt_status = NT_STATUS_OK;
1992 done:
1994 if (got_hnd_src)
1995 cli_spoolss_close_printer(cli, mem_ctx, &hnd_src);
1997 if (got_hnd_dst)
1998 cli_spoolss_close_printer(cli_dst, mem_ctx, &hnd_dst);
2000 if (got_dst_spoolss_pipe) {
2001 cli_nt_session_close(cli_dst);
2002 cli_shutdown(cli_dst);
2005 if (got_src_driver_share)
2006 cli_shutdown(cli_share_src);
2008 if (got_dst_driver_share)
2009 cli_shutdown(cli_share_dst);
2011 return nt_status;
2016 /**
2017 * Migrate printer-queues from a src to the dst server
2018 * (requires a working "addprinter command" to be installed for the local smbd)
2020 * All parameters are provided by the run_rpc_command function, except for
2021 * argc, argv which are passed through.
2023 * @param domain_sid The domain sid aquired from the remote server
2024 * @param cli A cli_state connected to the server.
2025 * @param mem_ctx Talloc context, destoyed on compleation of the function.
2026 * @param argc Standard main() style argc
2027 * @param argv Standard main() style argv. Initial components are already
2028 * stripped
2030 * @return Normal NTSTATUS return.
2032 NTSTATUS rpc_printer_migrate_printers_internals(const DOM_SID *domain_sid, const char *domain_name,
2033 struct cli_state *cli, TALLOC_CTX *mem_ctx,
2034 int argc, const char **argv)
2036 WERROR result;
2037 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
2038 uint32 i = 0, num_printers;
2039 uint32 level = 2;
2040 PRINTER_INFO_CTR ctr_src, ctr_dst, ctr_enum;
2041 struct cli_state *cli_dst = NULL;
2042 POLICY_HND hnd_dst, hnd_src;
2043 pstring printername, sharename;
2044 BOOL got_hnd_src = False;
2045 BOOL got_hnd_dst = False;
2046 BOOL got_dst_spoolss_pipe = False;
2048 DEBUG(3,("copying printers\n"));
2050 /* connect destination PI_SPOOLSS */
2051 nt_status = connect_pipe(&cli_dst, PI_SPOOLSS, &got_dst_spoolss_pipe);
2052 if (!NT_STATUS_IS_OK(nt_status))
2053 return nt_status;
2056 /* enum printers */
2057 if (!get_printer_info(cli, mem_ctx, 2, argc, argv, &num_printers, &ctr_enum)) {
2058 nt_status = NT_STATUS_UNSUCCESSFUL;
2059 goto done;
2062 if (!num_printers) {
2063 printf ("no printers found on server.\n");
2064 nt_status = NT_STATUS_OK;
2065 goto done;
2069 /* do something for all printers */
2070 for (i = 0; i < num_printers; i++) {
2072 /* do some initialization */
2073 rpcstr_pull(printername, ctr_enum.printers_2[i].printername.buffer,
2074 sizeof(printername), -1, STR_TERMINATE);
2075 rpcstr_pull(sharename, ctr_enum.printers_2[i].sharename.buffer,
2076 sizeof(sharename), -1, STR_TERMINATE);
2077 /* we can reset NT_STATUS here because we do not
2078 get any real NT_STATUS-codes anymore from now on */
2079 nt_status = NT_STATUS_UNSUCCESSFUL;
2081 d_printf("migrating printer queue for: [%s] / [%s]\n",
2082 printername, sharename);
2085 /* open dst printer handle */
2086 if (!net_spoolss_open_printer_ex(cli_dst, mem_ctx, sharename,
2087 PRINTER_ALL_ACCESS, cli->user_name, &hnd_dst)) {
2089 DEBUG(1,("could not open printer: %s\n", sharename));
2090 } else {
2091 got_hnd_dst = True;
2095 /* check for existing dst printer */
2096 if (!net_spoolss_getprinter(cli_dst, mem_ctx, &hnd_dst, level, &ctr_dst)) {
2097 printf ("could not get printer, creating printer.\n");
2098 } else {
2099 DEBUG(1,("printer already exists: %s\n", sharename));
2100 /* close printer handles here */
2101 if (got_hnd_src) {
2102 cli_spoolss_close_printer(cli, mem_ctx, &hnd_src);
2103 got_hnd_src = False;
2106 if (got_hnd_dst) {
2107 cli_spoolss_close_printer(cli_dst, mem_ctx, &hnd_dst);
2108 got_hnd_dst = False;
2110 continue;
2114 /* now get again src printer ctr via getprinter,
2115 we first need a handle for that */
2117 /* open src printer handle */
2118 if (!net_spoolss_open_printer_ex(cli, mem_ctx, sharename,
2119 MAXIMUM_ALLOWED_ACCESS, cli->user_name, &hnd_src))
2120 goto done;
2122 got_hnd_src = True;
2124 /* getprinter on the src server */
2125 if (!net_spoolss_getprinter(cli, mem_ctx, &hnd_src, level, &ctr_src))
2126 goto done;
2129 /* copy each src printer to a dst printer 1:1,
2130 maybe some values have to be changed though */
2131 d_printf("creating printer: %s\n", printername);
2132 result = cli_spoolss_addprinterex (cli_dst, mem_ctx, level, &ctr_src);
2134 if (W_ERROR_IS_OK(result))
2135 d_printf ("printer [%s] successfully added.\n", printername);
2136 else if (W_ERROR_V(result) == W_ERROR_V(WERR_PRINTER_ALREADY_EXISTS))
2137 d_printf ("printer [%s] already exists.\n", printername);
2138 else {
2139 printf ("could not create printer\n");
2140 goto done;
2143 /* close printer handles here */
2144 if (got_hnd_src) {
2145 cli_spoolss_close_printer(cli, mem_ctx, &hnd_src);
2146 got_hnd_src = False;
2149 if (got_hnd_dst) {
2150 cli_spoolss_close_printer(cli_dst, mem_ctx, &hnd_dst);
2151 got_hnd_dst = False;
2155 nt_status = NT_STATUS_OK;
2157 done:
2158 if (got_hnd_src)
2159 cli_spoolss_close_printer(cli, mem_ctx, &hnd_src);
2161 if (got_hnd_dst)
2162 cli_spoolss_close_printer(cli_dst, mem_ctx, &hnd_dst);
2164 if (got_dst_spoolss_pipe) {
2165 cli_nt_session_close(cli_dst);
2166 cli_shutdown(cli_dst);
2168 return nt_status;
2172 /**
2173 * Migrate Printer-Settings from a src server to the dst server
2174 * (for this to work, printers and drivers already have to be migrated earlier)
2176 * All parameters are provided by the run_rpc_command function, except for
2177 * argc, argv which are passed through.
2179 * @param domain_sid The domain sid aquired from the remote server
2180 * @param cli A cli_state connected to the server.
2181 * @param mem_ctx Talloc context, destoyed on compleation of the function.
2182 * @param argc Standard main() style argc
2183 * @param argv Standard main() style argv. Initial components are already
2184 * stripped
2186 * @return Normal NTSTATUS return.
2188 NTSTATUS rpc_printer_migrate_settings_internals(const DOM_SID *domain_sid, const char *domain_name,
2189 struct cli_state *cli, TALLOC_CTX *mem_ctx,
2190 int argc, const char **argv)
2193 /* FIXME: Here the nightmare begins */
2195 WERROR result;
2196 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
2197 uint32 i = 0, p = 0, j = 0;
2198 uint32 num_printers, val_needed, data_needed;
2199 uint32 level = 2;
2200 pstring printername = "", sharename = "";
2201 BOOL got_hnd_src = False;
2202 BOOL got_hnd_dst = False;
2203 BOOL got_dst_spoolss_pipe = False;
2204 POLICY_HND hnd_src, hnd_dst;
2205 PRINTER_INFO_CTR ctr_enum, ctr_dst, ctr_dst_publish;
2206 REGVAL_CTR reg_ctr;
2207 struct cli_state *cli_dst = NULL;
2208 char *devicename = NULL, *unc_name = NULL, *url = NULL;
2209 fstring longname;
2211 uint16 *keylist = NULL, *curkey;
2213 ZERO_STRUCT(ctr_enum);
2215 DEBUG(3,("copying printer settings\n"));
2217 /* connect destination PI_SPOOLSS */
2218 nt_status = connect_pipe(&cli_dst, PI_SPOOLSS, &got_dst_spoolss_pipe);
2219 if (!NT_STATUS_IS_OK(nt_status))
2220 return nt_status;
2223 /* enum src printers */
2224 if (!get_printer_info(cli, mem_ctx, level, argc, argv, &num_printers, &ctr_enum)) {
2225 nt_status = NT_STATUS_UNSUCCESSFUL;
2226 goto done;
2229 if (!num_printers) {
2230 printf ("no printers found on server.\n");
2231 nt_status = NT_STATUS_OK;
2232 goto done;
2236 /* needed for dns-strings in regkeys */
2237 get_mydnsfullname(longname);
2239 /* do something for all printers */
2240 for (i = 0; i < num_printers; i++) {
2242 /* do some initialization */
2243 rpcstr_pull(printername, ctr_enum.printers_2[i].printername.buffer,
2244 sizeof(printername), -1, STR_TERMINATE);
2245 rpcstr_pull(sharename, ctr_enum.printers_2[i].sharename.buffer,
2246 sizeof(sharename), -1, STR_TERMINATE);
2248 /* we can reset NT_STATUS here because we do not
2249 get any real NT_STATUS-codes anymore from now on */
2250 nt_status = NT_STATUS_UNSUCCESSFUL;
2252 d_printf("migrating printer settings for: [%s] / [%s]\n",
2253 printername, sharename);
2256 /* open src printer handle */
2257 if (!net_spoolss_open_printer_ex(cli, mem_ctx, sharename,
2258 MAXIMUM_ALLOWED_ACCESS, cli->user_name, &hnd_src))
2259 goto done;
2261 got_hnd_src = True;
2264 /* open dst printer handle */
2265 if (!net_spoolss_open_printer_ex(cli_dst, mem_ctx, sharename,
2266 PRINTER_ALL_ACCESS, cli_dst->user_name, &hnd_dst))
2267 goto done;
2269 got_hnd_dst = True;
2272 /* check for existing dst printer */
2273 if (!net_spoolss_getprinter(cli_dst, mem_ctx, &hnd_dst,
2274 level, &ctr_dst))
2275 goto done;
2278 /* STEP 1: COPY DEVICE-MODE and other
2279 PRINTER_INFO_2-attributes
2282 ctr_dst.printers_2 = &ctr_enum.printers_2[i];
2284 /* why is the port always disconnected when the printer
2285 is correctly installed (incl. driver ???) */
2286 init_unistr( &ctr_dst.printers_2->portname, SAMBA_PRINTER_PORT_NAME);
2288 /* check if printer is published */
2289 if (ctr_enum.printers_2[i].attributes & PRINTER_ATTRIBUTE_PUBLISHED) {
2291 /* check for existing dst printer */
2292 if (!net_spoolss_getprinter(cli_dst, mem_ctx, &hnd_dst, 7, &ctr_dst_publish))
2293 goto done;
2295 ctr_dst_publish.printers_7->action = SPOOL_DS_PUBLISH;
2297 /* ignore False from setprinter due to WERR_IO_PENDING */
2298 net_spoolss_setprinter(cli_dst, mem_ctx, &hnd_dst, 7, &ctr_dst_publish);
2300 DEBUG(3,("republished printer\n"));
2303 if (ctr_enum.printers_2[i].devmode != NULL) {
2305 /* copy devmode (info level 2) */
2306 ctr_dst.printers_2->devmode =
2307 TALLOC_MEMDUP(mem_ctx,
2308 ctr_enum.printers_2[i].devmode,
2309 sizeof(DEVICEMODE));
2311 /* do not copy security descriptor (we have another
2312 * command for that) */
2313 ctr_dst.printers_2->secdesc = NULL;
2315 #if 0
2316 if (asprintf(&devicename, "\\\\%s\\%s", longname,
2317 printername) < 0) {
2318 nt_status = NT_STATUS_NO_MEMORY;
2319 goto done;
2322 init_unistr(&ctr_dst.printers_2->devmode->devicename,
2323 devicename);
2324 #endif
2325 if (!net_spoolss_setprinter(cli_dst, mem_ctx, &hnd_dst,
2326 level, &ctr_dst))
2327 goto done;
2329 DEBUGADD(1,("\tSetPrinter of DEVICEMODE succeeded\n"));
2332 /* STEP 2: COPY REGISTRY VALUES */
2334 /* please keep in mind that samba parse_spools gives horribly
2335 crippled results when used to cli_spoolss_enumprinterdataex
2336 a win2k3-server. (Bugzilla #1851)
2337 FIXME: IIRC I've seen it too on a win2k-server
2340 /* enumerate data on src handle */
2341 result = cli_spoolss_enumprinterdata(cli, mem_ctx, &hnd_src, p, 0, 0,
2342 &val_needed, &data_needed, NULL);
2344 /* loop for all printerdata of "PrinterDriverData" */
2345 while (W_ERROR_IS_OK(result)) {
2347 REGISTRY_VALUE value;
2349 result = cli_spoolss_enumprinterdata(
2350 cli, mem_ctx, &hnd_src, p++, val_needed,
2351 data_needed, 0, 0, &value);
2353 /* loop for all reg_keys */
2354 if (W_ERROR_IS_OK(result)) {
2356 /* display_value */
2357 if (opt_verbose)
2358 display_reg_value(SPOOL_PRINTERDATA_KEY, value);
2360 /* set_value */
2361 if (!net_spoolss_setprinterdata(cli_dst, mem_ctx,
2362 &hnd_dst, &value))
2363 goto done;
2365 DEBUGADD(1,("\tSetPrinterData of [%s] succeeded\n",
2366 value.valuename));
2370 /* STEP 3: COPY SUBKEY VALUES */
2372 /* here we need to enum all printer_keys and then work
2373 on the result with enum_printer_key_ex. nt4 does not
2374 respond to enumprinterkey, win2k does, so continue
2375 in case of an error */
2377 if (!net_spoolss_enumprinterkey(cli, mem_ctx, &hnd_src, "", &keylist)) {
2378 printf("got no key-data\n");
2379 continue;
2383 /* work on a list of printer keys
2384 each key has to be enumerated to get all required
2385 information. information is then set via setprinterdataex-calls */
2387 if (keylist == NULL)
2388 continue;
2390 curkey = keylist;
2391 while (*curkey != 0) {
2393 pstring subkey;
2394 rpcstr_pull(subkey, curkey, sizeof(subkey), -1, STR_TERMINATE);
2396 curkey += strlen(subkey) + 1;
2398 /* enumerate all src subkeys */
2399 if (!net_spoolss_enumprinterdataex(cli, mem_ctx, 0,
2400 &hnd_src, subkey,
2401 &reg_ctr))
2402 goto done;
2404 for (j=0; j < reg_ctr.num_values; j++) {
2406 REGISTRY_VALUE value;
2407 UNISTR2 data;
2409 /* although samba replies with sane data in most cases we
2410 should try to avoid writing wrong registry data */
2412 if (strequal(reg_ctr.values[j]->valuename, SPOOL_REG_PORTNAME) ||
2413 strequal(reg_ctr.values[j]->valuename, SPOOL_REG_UNCNAME) ||
2414 strequal(reg_ctr.values[j]->valuename, SPOOL_REG_URL) ||
2415 strequal(reg_ctr.values[j]->valuename, SPOOL_REG_SHORTSERVERNAME) ||
2416 strequal(reg_ctr.values[j]->valuename, SPOOL_REG_SERVERNAME)) {
2418 if (strequal(reg_ctr.values[j]->valuename, SPOOL_REG_PORTNAME)) {
2420 /* although windows uses a multi-sz, we use a sz */
2421 init_unistr2(&data, SAMBA_PRINTER_PORT_NAME, UNI_STR_TERMINATE);
2422 fstrcpy(value.valuename, SPOOL_REG_PORTNAME);
2425 if (strequal(reg_ctr.values[j]->valuename, SPOOL_REG_UNCNAME)) {
2427 if (asprintf(&unc_name, "\\\\%s\\%s", longname, sharename) < 0) {
2428 nt_status = NT_STATUS_NO_MEMORY;
2429 goto done;
2431 init_unistr2(&data, unc_name, UNI_STR_TERMINATE);
2432 fstrcpy(value.valuename, SPOOL_REG_UNCNAME);
2435 if (strequal(reg_ctr.values[j]->valuename, SPOOL_REG_URL)) {
2437 continue;
2439 #if 0
2440 /* FIXME: should we really do that ??? */
2441 if (asprintf(&url, "http://%s:631/printers/%s", longname, sharename) < 0) {
2442 nt_status = NT_STATUS_NO_MEMORY;
2443 goto done;
2445 init_unistr2(&data, url, UNI_STR_TERMINATE);
2446 fstrcpy(value.valuename, SPOOL_REG_URL);
2447 #endif
2450 if (strequal(reg_ctr.values[j]->valuename, SPOOL_REG_SERVERNAME)) {
2452 init_unistr2(&data, longname, UNI_STR_TERMINATE);
2453 fstrcpy(value.valuename, SPOOL_REG_SERVERNAME);
2456 if (strequal(reg_ctr.values[j]->valuename, SPOOL_REG_SHORTSERVERNAME)) {
2458 init_unistr2(&data, global_myname(), UNI_STR_TERMINATE);
2459 fstrcpy(value.valuename, SPOOL_REG_SHORTSERVERNAME);
2462 value.type = REG_SZ;
2463 value.size = data.uni_str_len * 2;
2464 value.data_p = TALLOC_MEMDUP(mem_ctx, data.buffer, value.size);
2466 if (opt_verbose)
2467 display_reg_value(subkey, value);
2469 /* here we have to set all subkeys on the dst server */
2470 if (!net_spoolss_setprinterdataex(cli_dst, mem_ctx, &hnd_dst,
2471 subkey, &value))
2472 goto done;
2474 } else {
2476 if (opt_verbose)
2477 display_reg_value(subkey, *(reg_ctr.values[j]));
2479 /* here we have to set all subkeys on the dst server */
2480 if (!net_spoolss_setprinterdataex(cli_dst, mem_ctx, &hnd_dst,
2481 subkey, reg_ctr.values[j]))
2482 goto done;
2486 DEBUGADD(1,("\tSetPrinterDataEx of key [%s\\%s] succeeded\n",
2487 subkey, reg_ctr.values[j]->valuename));
2491 regval_ctr_destroy(&reg_ctr);
2494 safe_free(keylist);
2496 /* close printer handles here */
2497 if (got_hnd_src) {
2498 cli_spoolss_close_printer(cli, mem_ctx, &hnd_src);
2499 got_hnd_src = False;
2502 if (got_hnd_dst) {
2503 cli_spoolss_close_printer(cli_dst, mem_ctx, &hnd_dst);
2504 got_hnd_dst = False;
2509 nt_status = NT_STATUS_OK;
2511 done:
2512 SAFE_FREE(devicename);
2513 SAFE_FREE(url);
2514 SAFE_FREE(unc_name);
2516 if (got_hnd_src)
2517 cli_spoolss_close_printer(cli, mem_ctx, &hnd_src);
2519 if (got_hnd_dst)
2520 cli_spoolss_close_printer(cli_dst, mem_ctx, &hnd_dst);
2522 if (got_dst_spoolss_pipe) {
2523 cli_nt_session_close(cli_dst);
2524 cli_shutdown(cli_dst);
2526 return nt_status;