r2080: Remove last traces of static migration to localhost. Needed to allow a
[samba.git] / source3 / utils / net_rpc_printer.c
1 /* 
2    Samba Unix/Linux SMB client library 
3    Distributed SMB/CIFS Server Management Utility 
4    Copyright (C) 2004 Guenther Deschner (gd@samba.org)
5
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.
10    
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.
15    
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.  */
19  
20 #include "includes.h"
21 #include "../utils/net.h"
22
23 struct table_node {
24         const char *long_archi;
25         const char *short_archi;
26         int version;
27 };
28
29
30 /* support itanium as well */
31 static const struct table_node archi_table[]= {
32
33         {"Windows 4.0",          "WIN40",       0 },
34         {"Windows NT x86",       "W32X86",      2 },
35         {"Windows NT R4000",     "W32MIPS",     2 },
36         {"Windows NT Alpha_AXP", "W32ALPHA",    2 },
37         {"Windows NT PowerPC",   "W32PPC",      2 },
38         {"Windows IA64",         "IA64",        3 },
39         {NULL,                   "",            -1 }
40 };
41
42
43 /**
44  * The display-functions for Security-Descriptors were taken from rpcclient
45  * 
46  * They reside here for debugging purpose and should 
47  * possibly be removed later on
48  *
49  **/
50 /****************************************************************************
51 convert a security permissions into a string
52 ****************************************************************************/
53 char *get_sec_mask_str(uint32 type)
54 {
55         static fstring typestr="";
56
57         typestr[0] = 0;
58
59         if (type & GENERIC_ALL_ACCESS)
60                 fstrcat(typestr, "Generic all access ");
61         if (type & GENERIC_EXECUTE_ACCESS)
62                 fstrcat(typestr, "Generic execute access ");
63         if (type & GENERIC_WRITE_ACCESS)
64                 fstrcat(typestr, "Generic write access ");
65         if (type & GENERIC_READ_ACCESS)
66                 fstrcat(typestr, "Generic read access ");
67         if (type & MAXIMUM_ALLOWED_ACCESS)
68                 fstrcat(typestr, "MAXIMUM_ALLOWED_ACCESS ");
69         if (type & SYSTEM_SECURITY_ACCESS)
70                 fstrcat(typestr, "SYSTEM_SECURITY_ACCESS ");
71         if (type & SYNCHRONIZE_ACCESS)
72                 fstrcat(typestr, "SYNCHRONIZE_ACCESS ");
73         if (type & WRITE_OWNER_ACCESS)
74                 fstrcat(typestr, "WRITE_OWNER_ACCESS ");
75         if (type & WRITE_DAC_ACCESS)
76                 fstrcat(typestr, "WRITE_DAC_ACCESS ");
77         if (type & READ_CONTROL_ACCESS)
78                 fstrcat(typestr, "READ_CONTROL_ACCESS ");
79         if (type & DELETE_ACCESS)
80                 fstrcat(typestr, "DELETE_ACCESS ");
81
82         printf("\t\tSpecific bits: 0x%lx\n", (unsigned long)type&SPECIFIC_RIGHTS_MASK);
83
84         return typestr;
85 }
86
87
88 /****************************************************************************
89  display sec_ace structure
90  ****************************************************************************/
91 void display_sec_ace(SEC_ACE *ace)
92 {
93         fstring sid_str;
94
95         printf("\tACE\n\t\ttype: ");
96         switch (ace->type) {
97                 case SEC_ACE_TYPE_ACCESS_ALLOWED:
98                         printf("ACCESS ALLOWED");
99                         break;
100                 case SEC_ACE_TYPE_ACCESS_DENIED:
101                         printf("ACCESS DENIED");
102                         break;
103                 case SEC_ACE_TYPE_SYSTEM_AUDIT:
104                         printf("SYSTEM AUDIT");
105                         break;
106                 case SEC_ACE_TYPE_SYSTEM_ALARM:
107                         printf("SYSTEM ALARM");
108                         break;
109                 default:
110                         printf("????");
111                         break;
112         }
113         printf(" (%d) flags: %d\n", ace->type, ace->flags);
114         printf("\t\tPermissions: 0x%x: %s\n", ace->info.mask, get_sec_mask_str(ace->info.mask));
115
116         sid_to_string(sid_str, &ace->trustee);
117         printf("\t\tSID: %s\n\n", sid_str);
118 }
119
120
121 /****************************************************************************
122  display sec_acl structure
123  ****************************************************************************/
124 void display_sec_acl(SEC_ACL *sec_acl)
125 {
126         int i;
127
128         printf("\tACL\tNum ACEs:\t%d\trevision:\t%x\n",
129                          sec_acl->num_aces, sec_acl->revision); 
130         printf("\t---\n");
131
132         if (sec_acl->size != 0 && sec_acl->num_aces != 0)
133                 for (i = 0; i < sec_acl->num_aces; i++)
134                         display_sec_ace(&sec_acl->ace[i]);
135                                 
136 }
137
138 /****************************************************************************
139  display sec_desc structure
140  ****************************************************************************/
141 void display_sec_desc(SEC_DESC *sec)
142 {
143         fstring sid_str;
144
145         if (sec == NULL)
146                 return;
147
148         if (sec->sacl) {
149                 printf("SACL\n");
150                 display_sec_acl(sec->sacl);
151         }
152
153         if (sec->dacl) {
154                 printf("DACL\n");
155                 display_sec_acl(sec->dacl);
156         }
157
158         if (sec->owner_sid) {
159                 sid_to_string(sid_str, sec->owner_sid);
160                 printf("\tOwner SID:\t%s\n", sid_str);
161         }
162
163         if (sec->grp_sid) {
164                 sid_to_string(sid_str, sec->grp_sid);
165                 printf("\tParent SID:\t%s\n", sid_str);
166         }
167 }
168
169
170 /**
171  * This display-printdriver-functions was borrowed from rpcclient/cmd_spoolss.c.
172  * It is here for debugging purpose and should be removed later on.
173  **/
174
175 /****************************************************************************
176 printer info level 3 display function
177 ****************************************************************************/
178 static void display_print_driver_3(DRIVER_INFO_3 *i1)
179 {
180         fstring name = "";
181         fstring architecture = "";
182         fstring driverpath = "";
183         fstring datafile = "";
184         fstring configfile = "";
185         fstring helpfile = "";
186         fstring dependentfiles = "";
187         fstring monitorname = "";
188         fstring defaultdatatype = "";
189         
190         int length=0;
191         BOOL valid = True;
192         
193         if (i1 == NULL)
194                 return;
195
196         rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
197         rpcstr_pull(architecture, i1->architecture.buffer, sizeof(architecture), -1, STR_TERMINATE);
198         rpcstr_pull(driverpath, i1->driverpath.buffer, sizeof(driverpath), -1, STR_TERMINATE);
199         rpcstr_pull(datafile, i1->datafile.buffer, sizeof(datafile), -1, STR_TERMINATE);
200         rpcstr_pull(configfile, i1->configfile.buffer, sizeof(configfile), -1, STR_TERMINATE);
201         rpcstr_pull(helpfile, i1->helpfile.buffer, sizeof(helpfile), -1, STR_TERMINATE);
202         rpcstr_pull(monitorname, i1->monitorname.buffer, sizeof(monitorname), -1, STR_TERMINATE);
203         rpcstr_pull(defaultdatatype, i1->defaultdatatype.buffer, sizeof(defaultdatatype), -1, STR_TERMINATE);
204
205         d_printf ("Printer Driver Info 3:\n");
206         d_printf ("\tVersion: [%x]\n", i1->version);
207         d_printf ("\tDriver Name: [%s]\n",name);
208         d_printf ("\tArchitecture: [%s]\n", architecture);
209         d_printf ("\tDriver Path: [%s]\n", driverpath);
210         d_printf ("\tDatafile: [%s]\n", datafile);
211         d_printf ("\tConfigfile: [%s]\n", configfile);
212         d_printf ("\tHelpfile: [%s]\n\n", helpfile);
213
214         while (valid) {
215                 rpcstr_pull(dependentfiles, i1->dependentfiles+length, sizeof(dependentfiles), -1, STR_TERMINATE);
216                 
217                 length+=strlen(dependentfiles)+1;
218                 
219                 if (strlen(dependentfiles) > 0) {
220                         d_printf ("\tDependentfiles: [%s]\n", dependentfiles);
221                 } else {
222                         valid = False;
223                 }
224         }
225         
226         printf ("\n");
227
228         d_printf ("\tMonitorname: [%s]\n", monitorname);
229         d_printf ("\tDefaultdatatype: [%s]\n\n", defaultdatatype);
230
231         return; 
232 }
233
234
235 static void display_reg_value(pstring subkey, REGISTRY_VALUE value)
236 {
237         pstring text;
238
239         switch(value.type) {
240         case REG_DWORD:
241                 d_printf("\t[%s:%s]: REG_DWORD: 0x%08x\n", subkey, value.valuename, 
242                        *((uint32 *) value.data_p));
243                 break;
244
245         case REG_SZ:
246                 rpcstr_pull(text, value.data_p, sizeof(text), value.size,
247                             STR_TERMINATE);
248                 d_printf("\t[%s:%s]: REG_SZ: %s\n", subkey, value.valuename, text);
249                 break;
250
251         case REG_BINARY: 
252                 d_printf("\t[%s:%s]: REG_BINARY: unknown length value not displayed\n", 
253                          subkey, value.valuename);
254                 break;
255
256         case REG_MULTI_SZ: {
257                 uint16 *curstr = (uint16 *) value.data_p;
258                 uint8 *start = value.data_p;
259                 d_printf("\t[%s:%s]: REG_MULTI_SZ:\n", subkey, value.valuename);
260                 while ((*curstr != 0) && 
261                        ((uint8 *) curstr < start + value.size)) {
262                         rpcstr_pull(text, curstr, sizeof(text), -1, 
263                                     STR_TERMINATE);
264                         d_printf("%s\n", text);
265                         curstr += strlen(text) + 1;
266                 }
267         }
268         break;
269
270         default:
271                 d_printf("\t%s: unknown type %d\n", value.valuename, value.type);
272         }
273         
274 }
275
276
277 /**
278  * Copies ACLs, DOS-attributes and timestamps from one 
279  * file or directory from one connected share to another connected share 
280  *
281  * @param mem_ctx               A talloc-context
282  * @param cli_share_src         A connected cli_state 
283  * @param cli_share_dst         A connected cli_state 
284  * @param src_file              The source file-name
285  * @param dst_file              The destination file-name
286  * @param copy_acls             Whether to copy acls
287  * @param copy_attrs            Whether to copy DOS attributes
288  * @param copy_timestamps       Whether to preserve timestamps
289  * @param is_file               Whether this file is a file or a dir
290  *
291  * @return Normal NTSTATUS return.
292  **/ 
293 static NTSTATUS 
294 net_copy_fileattr(TALLOC_CTX *mem_ctx,
295                   struct cli_state *cli_share_src,
296                   struct cli_state *cli_share_dst, 
297                   char *src_name, char *dst_name,
298                   BOOL copy_acls, BOOL copy_attrs,
299                   BOOL copy_timestamps, BOOL is_file)
300 {
301         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
302         int fnum_src = 0;
303         int fnum_dst = 0;
304         SEC_DESC *sd = NULL;
305         uint16 attr;
306         time_t atime, ctime, mtime;
307
308
309         if (!copy_timestamps && !copy_acls && !copy_attrs)
310                 return NT_STATUS_OK;
311
312
313         /* open file/dir on the originating server */
314
315         DEBUGADD(3,("opening %s %s on originating server\n", 
316                 is_file?"file":"dir", src_name));
317
318         fnum_src = cli_nt_create(cli_share_src, src_name, READ_CONTROL_ACCESS);
319         if (fnum_src == -1) {
320                 DEBUGADD(0,("cannot open %s %s on originating server %s\n", 
321                         is_file?"file":"dir", src_name, cli_errstr(cli_share_src)));
322                 nt_status = cli_nt_error(cli_share_src);
323                 goto out;
324         }
325
326
327         if (copy_acls) {
328
329                 /* get the security descriptor */
330                 sd = cli_query_secdesc(cli_share_src, fnum_src, mem_ctx);
331                 if (!sd) {
332                         DEBUG(0,("failed to get security descriptor: %s\n",
333                                 cli_errstr(cli_share_src)));
334                         nt_status = cli_nt_error(cli_share_src);
335                         goto out;
336                 }
337
338                 if (opt_verbose && DEBUGLEVEL >= 3)
339                         display_sec_desc(sd);
340         }
341
342
343         if (copy_attrs || copy_timestamps) {
344
345                 /* get file attributes */
346                 if (!cli_getattrE(cli_share_src, fnum_src, &attr, NULL, 
347                                  &ctime, &atime, &mtime)) {
348                         DEBUG(0,("failed to get file-attrs: %s\n", 
349                                 cli_errstr(cli_share_src)));
350                         nt_status = cli_nt_error(cli_share_src);
351                         goto out;
352                 }
353         }
354
355
356         /* open the file/dir on the destination server */ 
357
358         fnum_dst = cli_nt_create(cli_share_dst, dst_name, WRITE_DAC_ACCESS | WRITE_OWNER_ACCESS);
359         if (fnum_dst == -1) {
360                 DEBUG(0,("failed to open %s on the destination server: %s: %s\n",
361                         is_file?"file":"dir", dst_name, cli_errstr(cli_share_dst)));
362                 nt_status = cli_nt_error(cli_share_dst);
363                 goto out;
364         }
365
366         if (copy_timestamps) {
367
368                 /* set timestamps */
369                 if (!cli_setattrE(cli_share_dst, fnum_dst, ctime, atime, mtime)) {
370                         DEBUG(0,("failed to set file-attrs (timestamps): %s\n",
371                                 cli_errstr(cli_share_dst)));
372                         nt_status = cli_nt_error(cli_share_dst);
373                         goto out;
374                 }
375         }
376
377         if (copy_acls) {
378
379                 /* set acls */
380                 if (!cli_set_secdesc(cli_share_dst, fnum_dst, sd)) {
381                         DEBUG(0,("could not set secdesc on %s: %s\n",
382                                 dst_name, cli_errstr(cli_share_dst)));
383                         nt_status = cli_nt_error(cli_share_dst);
384                         goto out;
385                 }
386         }
387
388         if (copy_attrs) {
389
390                 /* set attrs */
391                 if (!cli_setatr(cli_share_dst, dst_name, attr, 0)) {
392                         DEBUG(0,("failed to set file-attrs: %s\n",
393                                 cli_errstr(cli_share_dst)));
394                         nt_status = cli_nt_error(cli_share_dst);
395                         goto out;
396                 }
397         }
398
399
400         /* closing files */
401
402         if (!cli_close(cli_share_src, fnum_src)) {
403                 d_printf("could not close %s on originating server: %s\n", 
404                         is_file?"file":"dir", cli_errstr(cli_share_src));
405                 nt_status = cli_nt_error(cli_share_src);
406                 goto out;
407         }
408
409         if (!cli_close(cli_share_dst, fnum_dst)) {
410                 d_printf("could not close %s on destination server: %s\n", 
411                         is_file?"file":"dir", cli_errstr(cli_share_dst));
412                 nt_status = cli_nt_error(cli_share_dst);
413                 goto out;
414         }
415
416
417         nt_status = NT_STATUS_OK;
418
419 out:
420
421         /* cleaning up */
422         if (fnum_src)
423                 cli_close(cli_share_src, fnum_src);
424
425         if (fnum_dst)
426                 cli_close(cli_share_dst, fnum_dst);
427
428         return nt_status;
429 }
430
431
432 /**
433  * Copy a file or directory from a connected share to another connected share 
434  *
435  * @param mem_ctx               A talloc-context
436  * @param cli_share_src         A connected cli_state 
437  * @param cli_share_dst         A connected cli_state 
438  * @param src_file              The source file-name
439  * @param dst_file              The destination file-name
440  * @param copy_acls             Whether to copy acls
441  * @param copy_attrs            Whether to copy DOS attributes
442  * @param copy_timestamps       Whether to preserve timestamps
443  * @param is_file               Whether this file is a file or a dir
444  *
445  * @return Normal NTSTATUS return.
446  **/ 
447 NTSTATUS net_copy_file(TALLOC_CTX *mem_ctx,
448                        struct cli_state *cli_share_src,
449                        struct cli_state *cli_share_dst, 
450                        char *src_name, char *dst_name,
451                        BOOL copy_acls, BOOL copy_attrs,
452                        BOOL copy_timestamps, BOOL is_file)
453 {
454         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
455         int fnum_src = 0;
456         int fnum_dst = 0;
457         static int io_bufsize = 64512;
458         int read_size = io_bufsize;
459         char *data = NULL;
460         off_t start = 0;
461         off_t nread = 0;
462
463
464         if (!src_name || !dst_name)
465                 goto out;
466
467         if (cli_share_dst == NULL || cli_share_dst == NULL)
468                 goto out; 
469                 
470
471         /* open on the originating server */
472         DEBUGADD(3,("opening %s %s on originating server\n", 
473                 is_file ? "file":"dir", src_name));
474         if (is_file)
475                 fnum_src = cli_open(cli_share_src, src_name, O_RDONLY, DENY_NONE);
476         else
477                 fnum_src = cli_nt_create(cli_share_src, src_name, READ_CONTROL_ACCESS);
478
479         if (fnum_src == -1) {
480                 DEBUGADD(0,("cannot open file %s on originating server %s\n", 
481                         src_name, cli_errstr(cli_share_src)));
482                 nt_status = cli_nt_error(cli_share_src);
483                 goto out;
484         }
485
486
487         if (is_file) {
488
489                 /* open file on the destination server */
490                 DEBUGADD(3,("opening file %s on destination server\n", dst_name));
491                 fnum_dst = cli_open(cli_share_dst, dst_name, 
492                                 O_RDWR|O_CREAT|O_TRUNC, DENY_NONE);
493
494                 if (fnum_dst == -1) {
495                         DEBUGADD(1,("cannot create file %s on destination server: %s\n", 
496                                 dst_name, cli_errstr(cli_share_dst)));
497                         nt_status = cli_nt_error(cli_share_dst);
498                         goto out;
499                 }
500
501                 /* allocate memory */
502                 if (!(data = (char *)malloc(read_size))) {
503                         d_printf("malloc fail for size %d\n", read_size);
504                         nt_status = NT_STATUS_NO_MEMORY;
505                         goto out;
506                 }
507
508         }
509
510
511         if (opt_verbose) {
512
513                 d_printf("copying [\\\\%s\\%s%s] => [\\\\%s\\%s%s] "
514                          "%s ACLs and %s DOS Attributes %s\n", 
515                         cli_share_src->desthost, cli_share_src->share, src_name,
516                         cli_share_dst->desthost, cli_share_dst->share, dst_name,
517                         copy_acls ?  "with" : "without", 
518                         copy_attrs ? "with" : "without",
519                         copy_timestamps ? "(preserving timestamps)" : "" );
520         }
521
522
523         while (is_file) {
524
525                 /* copying file */
526                 int n, ret;
527                 n = cli_read(cli_share_src, fnum_src, data, nread + start, 
528                                 read_size);
529
530                 if (n <= 0)
531                         break;
532
533                 ret = cli_write(cli_share_dst, fnum_dst, 0, data, 
534                         nread + start, n);
535
536                 if (n != ret) {
537                         d_printf("Error writing file: %s\n", 
538                                 cli_errstr(cli_share_dst));
539                         nt_status = cli_nt_error(cli_share_dst);
540                         goto out;
541                 }
542
543                 nread += n;
544         }
545
546
547         if (!is_file && !cli_chkpath(cli_share_dst, dst_name)) {
548
549                 /* creating dir */
550                 DEBUGADD(3,("creating dir %s on the destination server\n", 
551                         dst_name));
552
553                 if (!cli_mkdir(cli_share_dst, dst_name)) {
554                         DEBUG(0,("cannot create directory %s: %s\n",
555                                 dst_name, cli_errstr(cli_share_dst)));
556                         nt_status = NT_STATUS_NO_SUCH_FILE;
557                 }
558
559                 if (!cli_chkpath(cli_share_dst, dst_name)) {
560                         d_printf("cannot check for directory %s: %s\n",
561                                 dst_name, cli_errstr(cli_share_dst));
562                         goto out;
563                 }
564         }
565
566
567         /* closing files */
568         if (!cli_close(cli_share_src, fnum_src)) {
569                 d_printf("could not close file on originating server: %s\n", 
570                         cli_errstr(cli_share_src));
571                 nt_status = cli_nt_error(cli_share_src);
572                 goto out;
573         }
574
575         if (is_file && !cli_close(cli_share_dst, fnum_dst)) {
576                 d_printf("could not close file on destination server: %s\n", 
577                         cli_errstr(cli_share_dst));
578                 nt_status = cli_nt_error(cli_share_dst);
579                 goto out;
580         }
581
582         /* possibly we have to copy some file-attributes / acls / sd */
583         nt_status = net_copy_fileattr(mem_ctx, cli_share_src, cli_share_dst, 
584                                       src_name, dst_name, copy_acls, 
585                                       copy_attrs, copy_timestamps, is_file);
586         if (!NT_STATUS_IS_OK(nt_status))
587                 goto out;
588
589
590         nt_status = NT_STATUS_OK;
591
592 out:
593
594         /* cleaning up */
595         if (fnum_src)
596                 cli_close(cli_share_src, fnum_src);
597
598         if (fnum_dst)
599                 cli_close(cli_share_dst, fnum_dst);
600
601         SAFE_FREE(data);
602
603         return nt_status;
604 }
605
606
607 /**
608  * Copy a driverfile from on connected share to another connected share 
609  * This silently assumes that a driver-file is picked up from 
610  *
611  *      \\src_server\print$\{arch}\{version}\file 
612  *
613  * and copied to
614  *
615  *      \\dst_server\print$\{arch}\file 
616  * 
617  * to be added via setdriver-calls later.
618  * @param mem_ctx               A talloc-context
619  * @param cli_share_src         A cli_state connected to source print$-share
620  * @param cli_share_dst         A cli_state connected to destination print$-share
621  * @param file                  The file-name to be copied 
622  * @param short_archi           The name of the driver-architecture (short form)
623  *
624  * @return Normal NTSTATUS return.
625  **/ 
626 static NTSTATUS net_copy_driverfile(TALLOC_CTX *mem_ctx,
627                                     struct cli_state *cli_share_src,
628                                     struct cli_state *cli_share_dst, 
629                                     char *file, const char *short_archi) {
630
631         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
632         const char *p;
633         char *src_name;
634         char *dst_name;
635         fstring version;
636         fstring filename;
637         fstring tok;
638
639         /* scroll through the file until we have the part 
640            beyond archi_table.short_archi */
641         p = file;
642         while (next_token(&p, tok, "\\", sizeof(tok))) {
643                 if (strequal(tok, short_archi)) {
644                         next_token(&p, version, "\\", sizeof(version));
645                         next_token(&p, filename, "\\", sizeof(filename));
646                 }
647         }
648
649         /* build source file name */
650         if (asprintf(&src_name, "\\%s\\%s\\%s", short_archi, version, filename) < 0 ) 
651                 return NT_STATUS_NO_MEMORY;
652
653
654         /* create destination file name */
655         if (asprintf(&dst_name, "\\%s\\%s", short_archi, filename) < 0 )
656                 return NT_STATUS_NO_MEMORY;
657
658
659         /* finally copy the file */
660         nt_status = net_copy_file(mem_ctx, cli_share_src, cli_share_dst, 
661                                   src_name, dst_name, False, False, False, True);
662         if (!NT_STATUS_IS_OK(nt_status))
663                 goto out;
664
665         nt_status = NT_STATUS_OK;
666
667 out:
668         SAFE_FREE(src_name);
669         SAFE_FREE(dst_name);
670
671         return nt_status;
672 }
673
674
675 /**
676  * Check for existing Architecture directory on a given server
677  *
678  * @param cli_share             A cli_state connected to a print$-share
679  * @param short_archi           The Architecture for the print-driver
680  *
681  * @return Normal NTSTATUS return.
682  **/
683 static NTSTATUS 
684 check_arch_dir(struct cli_state *cli_share, const char *short_archi)
685 {
686
687         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
688         char *dir;
689
690         if (asprintf(&dir, "\\%s", short_archi) < 0) {
691                 return NT_STATUS_NO_MEMORY;
692         }
693
694         DEBUG(10,("creating print-driver dir for architecture: %s\n", 
695                 short_archi));
696
697         if (!cli_mkdir(cli_share, dir)) {
698                 DEBUG(1,("cannot create directory %s: %s\n",
699                          dir, cli_errstr(cli_share)));
700                 nt_status = NT_STATUS_NO_SUCH_FILE;
701         }
702
703         if (!cli_chkpath(cli_share, dir)) {
704                 d_printf("cannot check %s: %s\n", 
705                         dir, cli_errstr(cli_share));
706                 goto out;
707         }
708
709         nt_status = NT_STATUS_OK;
710
711 out:
712         SAFE_FREE(dir);
713         return nt_status;
714 }
715
716
717 /**
718  * Copy a print-driver (level 3) from one connected print$-share to another 
719  * connected print$-share
720  *
721  * @param mem_ctx               A talloc-context
722  * @param cli_share_src         A cli_state connected to a print$-share
723  * @param cli_share_dst         A cli_state connected to a print$-share
724  * @param short_archi           The Architecture for the print-driver
725  * @param i1                    The DRIVER_INFO_3-struct
726  *
727  * @return Normal NTSTATUS return.
728  **/
729 static NTSTATUS 
730 copy_print_driver_3(TALLOC_CTX *mem_ctx,
731                     struct cli_state *cli_share_src, 
732                     struct cli_state *cli_share_dst, 
733                     const char *short_archi, DRIVER_INFO_3 *i1)
734 {
735         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
736         int length = 0;
737         BOOL valid = True;
738         
739         fstring name = "";
740         fstring driverpath = "";
741         fstring datafile = "";
742         fstring configfile = "";
743         fstring helpfile = "";
744         fstring dependentfiles = "";
745         
746         if (i1 == NULL)
747                 return nt_status;
748
749         rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
750         rpcstr_pull(driverpath, i1->driverpath.buffer, sizeof(driverpath), -1, STR_TERMINATE);
751         rpcstr_pull(datafile, i1->datafile.buffer, sizeof(datafile), -1, STR_TERMINATE);
752         rpcstr_pull(configfile, i1->configfile.buffer, sizeof(configfile), -1, STR_TERMINATE);
753         rpcstr_pull(helpfile, i1->helpfile.buffer, sizeof(helpfile), -1, STR_TERMINATE);
754
755
756         if (opt_verbose)
757                 d_printf("copying driver: [%s], for architecture: [%s], version: [%d]\n", 
758                           name, short_archi, i1->version);
759         
760         nt_status = net_copy_driverfile(mem_ctx, cli_share_src, cli_share_dst, 
761                 driverpath, short_archi);
762         if (!NT_STATUS_IS_OK(nt_status))
763                 return nt_status;
764                 
765         nt_status = net_copy_driverfile(mem_ctx, cli_share_src, cli_share_dst, 
766                 datafile, short_archi);
767         if (!NT_STATUS_IS_OK(nt_status))
768                 return nt_status;
769                 
770         nt_status = net_copy_driverfile(mem_ctx, cli_share_src, cli_share_dst, 
771                 configfile, short_archi);
772         if (!NT_STATUS_IS_OK(nt_status))
773                 return nt_status;
774                 
775         nt_status = net_copy_driverfile(mem_ctx, cli_share_src, cli_share_dst, 
776                 helpfile, short_archi);
777         if (!NT_STATUS_IS_OK(nt_status))
778                 return nt_status;
779
780         while (valid) {
781                 rpcstr_pull(dependentfiles, i1->dependentfiles+length, sizeof(dependentfiles), -1, STR_TERMINATE);
782                 length+=strlen(dependentfiles)+1;
783                 if (strlen(dependentfiles) > 0) {
784
785                         nt_status = net_copy_driverfile(mem_ctx, 
786                                         cli_share_src, cli_share_dst, 
787                                         dependentfiles, short_archi);
788                         if (!NT_STATUS_IS_OK(nt_status))
789                                 return nt_status;
790                 } else {
791                         valid = False;
792                 }
793         }
794
795         return NT_STATUS_OK;
796 }
797
798
799 /**
800  * net_spoolss-functions
801  * =====================
802  *
803  * the net_spoolss-functions aim to simplify spoolss-client-functions
804  * required during the migration-process wrt buffer-sizes, returned
805  * error-codes, etc. 
806  *
807  * this greatly reduces the complexitiy of the migrate-functions.
808  *
809  **/
810
811 static BOOL
812 net_spoolss_enum_printers(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
813                           char *name, uint32 flags, uint32 level, 
814                           uint32 *num_printers, PRINTER_INFO_CTR *ctr)
815 {
816
817         WERROR result;
818         uint32 needed;
819
820         /* enum printers */
821         result = cli_spoolss_enum_printers(
822                 cli, mem_ctx, 0, &needed, name, flags,
823                 level, num_printers, ctr);
824
825         if (W_ERROR_V(result) == W_ERROR_V(WERR_INSUFFICIENT_BUFFER)) 
826                 result = cli_spoolss_enum_printers(
827                         cli, mem_ctx, needed, NULL, name, flags,
828                         level, num_printers, ctr);
829         
830
831         if (!W_ERROR_IS_OK(result)) {
832                 printf("cannot enum printers: %s\n", dos_errstr(result));
833                 return False;
834         }
835
836         return True;
837 }
838
839
840 static BOOL
841 net_spoolss_open_printer_ex(struct cli_state *cli, TALLOC_CTX *mem_ctx,
842                             const char *printername, const char *datatype, 
843                             uint32 access_required, const char *servername, 
844                             const char *username, POLICY_HND *hnd)
845 {
846         WERROR result;
847
848         fstring servername2;
849         slprintf(servername2, sizeof(servername2)-1, "\\\\%s", cli->desthost);
850
851         DEBUG(10,("connecting to: %s as %s for %s and access: %x\n", 
852                 servername2, username, printername, access_required));
853
854         /* open printer */
855         result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername,
856                         "", access_required,
857                         servername2, username, hnd);
858
859         /* be more verbose */
860         if (W_ERROR_V(result) == W_ERROR_V(WERR_ACCESS_DENIED)) {
861                 d_printf("no access to printer [%s] on [%s] for user [%s] granted\n", 
862                         printername, servername2, username);
863                 return False;
864         }
865
866         if (!W_ERROR_IS_OK(result)) {
867                 d_printf("cannot open printer %s on server %s: %s\n", 
868                         printername, servername2, dos_errstr(result));
869                 return False;
870         }
871
872         DEBUG(2,("got printer handle for printer: %s, server: %s\n", 
873                 printername, servername2));
874
875         return True;
876 }
877
878
879 static BOOL
880 net_spoolss_getprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx,
881                        POLICY_HND *hnd, uint32 level, 
882                        PRINTER_INFO_CTR *ctr)
883 {
884         WERROR result;
885         uint32 needed;
886
887         /* getprinter call */
888         result = cli_spoolss_getprinter(cli, 
889                 mem_ctx, 0, &needed, hnd, level, ctr);
890
891         if (W_ERROR_V(result) == W_ERROR_V(WERR_INSUFFICIENT_BUFFER)) 
892                 result = cli_spoolss_getprinter(cli, 
893                         mem_ctx, needed, NULL, hnd, level, ctr);
894                         
895         if (!W_ERROR_IS_OK(result)) {
896                 printf("cannot get printer-info: %s\n", dos_errstr(result));
897                 return False;
898         }
899
900         return True;
901 }
902
903
904 static BOOL
905 net_spoolss_setprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx,
906                        POLICY_HND *hnd, uint32 level, 
907                        PRINTER_INFO_CTR *ctr)
908 {
909         WERROR result;
910
911         /* setprinter call */
912         result = cli_spoolss_setprinter(cli, mem_ctx, hnd, level, ctr, 0);
913
914         if (!W_ERROR_IS_OK(result)) {
915                 printf("cannot set printer-info: %s\n", dos_errstr(result));
916                 return False;
917         }
918
919         return True;
920 }
921
922
923 static BOOL
924 net_spoolss_setprinterdata(struct cli_state *cli, TALLOC_CTX *mem_ctx,
925                            POLICY_HND *hnd, REGISTRY_VALUE *value)
926 {
927         WERROR result;
928         
929         /* setprinterdata call */
930         result = cli_spoolss_setprinterdata(cli, mem_ctx, hnd, value);
931
932         if (!W_ERROR_IS_OK(result)) {
933                 printf ("unable to set printerdata: %s\n", dos_errstr(result));
934                 return False;
935         }
936
937         return True;
938 }
939
940
941 static BOOL
942 net_spoolss_enumprinterkey(struct cli_state *cli, TALLOC_CTX *mem_ctx,
943                            POLICY_HND *hnd, const char *keyname,
944                            uint16 **keylist)
945 {
946         WERROR result;
947         uint32 needed, len;
948
949         /* enumprinterkey call */
950         result = cli_spoolss_enumprinterkey(
951                 cli, mem_ctx, 0, &needed, hnd, keyname, NULL, NULL);
952                 
953         if (W_ERROR_V(result) == W_ERROR_V(WERR_MORE_DATA)) 
954                 result = cli_spoolss_enumprinterkey(
955                         cli, mem_ctx, needed, NULL, hnd, keyname, keylist,
956                         &len);
957
958         if (!W_ERROR_IS_OK(result)) {
959                 printf("enumprinterkey failed: %s\n", dos_errstr(result));
960                 return False;
961         }
962         
963         return True;
964 }
965
966
967 static BOOL
968 net_spoolss_enumprinterdataex(struct cli_state *cli, TALLOC_CTX *mem_ctx,
969                               uint32 offered, 
970                               POLICY_HND *hnd, const char *keyname, 
971                               REGVAL_CTR *ctr) 
972 {
973         WERROR result;
974         uint32 needed;
975
976         /* enumprinterdataex call */
977         result = cli_spoolss_enumprinterdataex(
978                 cli, mem_ctx, 0, &needed, hnd, keyname, NULL);
979                         
980         if (W_ERROR_V(result) == W_ERROR_V(WERR_MORE_DATA)) 
981                 result = cli_spoolss_enumprinterdataex(
982                         cli, mem_ctx, needed, NULL, hnd, keyname, ctr);
983                                         
984         if (!W_ERROR_IS_OK(result)) {
985                 printf("enumprinterdataex failed: %s\n", dos_errstr(result));
986                 return False;
987         }
988         
989         return True;
990 }
991
992
993 static BOOL 
994 net_spoolss_setprinterdataex(struct cli_state *cli, TALLOC_CTX *mem_ctx,
995                              POLICY_HND *hnd, char *keyname, 
996                              REGISTRY_VALUE *value)
997 {
998         WERROR result;
999
1000         /* setprinterdataex call */
1001         result = cli_spoolss_setprinterdataex(cli, mem_ctx, hnd, 
1002                                               keyname, value);
1003         
1004         if (!W_ERROR_IS_OK(result)) {
1005                 printf("could not set printerdataex: %s\n", dos_errstr(result));
1006                 return False;
1007         }
1008         
1009         return True;
1010 }
1011
1012
1013 static BOOL
1014 net_spoolss_enumforms(struct cli_state *cli, TALLOC_CTX *mem_ctx,
1015                       POLICY_HND *hnd, int level, uint32 *num_forms,
1016                       FORM_1 **forms)
1017                                                                                        
1018 {
1019         WERROR result;
1020         uint32 needed;
1021
1022         /* enumforms call */
1023         result = cli_spoolss_enumforms(
1024                         cli, mem_ctx, 0, &needed, hnd, level, num_forms, forms);
1025
1026         if (W_ERROR_V(result) == W_ERROR_V(WERR_INSUFFICIENT_BUFFER)) 
1027                 result = cli_spoolss_enumforms(
1028                                 cli, mem_ctx, needed, NULL, hnd, level,
1029                                 num_forms, forms);
1030
1031         if (!W_ERROR_IS_OK(result)) {
1032                 printf("could not enum forms: %s\n", dos_errstr(result));
1033                 return False;
1034         }
1035         
1036         return True;
1037 }
1038
1039
1040 static BOOL
1041 net_spoolss_enumprinterdrivers (struct cli_state *cli, TALLOC_CTX *mem_ctx,
1042                                 uint32 level, const char *env,
1043                                 uint32 *num_drivers,
1044                                 PRINTER_DRIVER_CTR *ctr)
1045 {
1046         WERROR result;
1047         uint32 needed;
1048
1049         /* enumprinterdrivers call */
1050         result = cli_spoolss_enumprinterdrivers(
1051                         cli, mem_ctx, 0, &needed, level,
1052                         env, num_drivers, ctr);
1053
1054         if (W_ERROR_V(result) == W_ERROR_V(WERR_INSUFFICIENT_BUFFER))
1055                 result = cli_spoolss_enumprinterdrivers(
1056                                 cli, mem_ctx, needed, NULL, level,
1057                                 env, num_drivers, ctr);
1058         
1059         if (!W_ERROR_IS_OK(result)) {
1060                 printf("cannot enum drivers: %s\n", dos_errstr(result));
1061                 return False;
1062         }
1063
1064         return True;
1065 }
1066
1067
1068 static BOOL
1069 net_spoolss_getprinterdriver(struct cli_state *cli, 
1070                              TALLOC_CTX *mem_ctx, 
1071                              POLICY_HND *hnd, uint32 level, 
1072                              const char *env, int version, 
1073                              PRINTER_DRIVER_CTR *ctr)
1074 {
1075         WERROR result;
1076         uint32 needed;
1077         
1078         /* getprinterdriver call */
1079         result = cli_spoolss_getprinterdriver(
1080                         cli, mem_ctx, 0, &needed, hnd, level,
1081                         env, version, ctr);
1082
1083         if (W_ERROR_V(result) == W_ERROR_V(WERR_INSUFFICIENT_BUFFER))
1084                 result = cli_spoolss_getprinterdriver(
1085                                 cli, mem_ctx, needed, NULL, hnd, level,
1086                                 env, version, ctr);
1087
1088         if (!W_ERROR_IS_OK(result)) {
1089                 DEBUG(1,("cannot get driver (for architecture: %s): %s\n", 
1090                         env, dos_errstr(result)));
1091                 if (W_ERROR_V(result) != W_ERROR_V(WERR_UNKNOWN_PRINTER_DRIVER)) {
1092                         printf("cannot get driver: %s\n", dos_errstr(result));
1093                 }
1094                 return False;
1095         }
1096
1097         return True;
1098 }
1099
1100
1101 static BOOL
1102 net_spoolss_addprinterdriver(struct cli_state *cli, 
1103                              TALLOC_CTX *mem_ctx, uint32 level,
1104                              PRINTER_DRIVER_CTR *ctr)
1105 {
1106         WERROR result;
1107
1108         /* addprinterdriver call */
1109         result = cli_spoolss_addprinterdriver(cli, mem_ctx, level, ctr);
1110
1111         /* be more verbose */
1112         if (W_ERROR_V(result) == W_ERROR_V(WERR_ACCESS_DENIED)) {
1113                 printf("You are not allowed to add drivers\n");
1114                 return False;
1115         }
1116         if (!W_ERROR_IS_OK(result)) {
1117                 printf("cannot add driver: %s\n", dos_errstr(result));
1118                 return False;
1119         }
1120
1121         return True;
1122 }
1123
1124 /**
1125  * abstraction function to get uint32 num_printers and PRINTER_INFO_CTR ctr 
1126  * for a single printer or for all printers depending on argc/argv 
1127  **/
1128 static BOOL
1129 get_printer_info(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
1130                  int level, int argc, const char **argv, 
1131                  uint32 *num_printers, PRINTER_INFO_CTR *ctr)
1132 {
1133
1134         char *sharename;
1135         fstring servername;
1136         POLICY_HND hnd;
1137
1138         /* no arguments given, enumerate all printers */
1139         if (argc == 0) {
1140
1141                 if (!net_spoolss_enum_printers(cli, mem_ctx, NULL, 
1142                                 PRINTER_ENUM_LOCAL|PRINTER_ENUM_SHARED, 
1143                                 level, num_printers, ctr)) 
1144                         return False;
1145
1146                 goto out;
1147         }
1148
1149
1150         /* argument given, get a single printer by name */
1151         sharename = strdup(argv[0]);
1152
1153         if (!net_spoolss_open_printer_ex(cli, mem_ctx, sharename, "", 
1154                         MAXIMUM_ALLOWED_ACCESS, servername, 
1155                         cli->user_name, &hnd)) 
1156                 return False;
1157
1158         if (!net_spoolss_getprinter(cli, mem_ctx, &hnd, level, ctr)) {
1159                 cli_spoolss_close_printer(cli, mem_ctx, &hnd);
1160                 return False;
1161         }
1162
1163         cli_spoolss_close_printer(cli, mem_ctx, &hnd);
1164
1165         *num_printers = 1;
1166
1167 out:
1168         DEBUG(3,("got %d printers\n", *num_printers));
1169
1170         return True;
1171
1172 }
1173
1174
1175 /** 
1176  * List print-queues (including local printers that are not shared)
1177  *
1178  * All parameters are provided by the run_rpc_command function, except for
1179  * argc, argv which are passed through. 
1180  *
1181  * @param domain_sid The domain sid aquired from the remote server
1182  * @param cli A cli_state connected to the server.
1183  * @param mem_ctx Talloc context, destoyed on compleation of the function.
1184  * @param argc  Standard main() style argc
1185  * @param argv  Standard main() style argv.  Initial components are already
1186  *              stripped
1187  *
1188  * @return Normal NTSTATUS return.
1189  **/
1190 NTSTATUS rpc_printer_list_internals(const DOM_SID *domain_sid, const char *domain_name, 
1191                                     struct cli_state *cli, TALLOC_CTX *mem_ctx, 
1192                                     int argc, const char **argv)
1193 {
1194         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1195         uint32 i, num_printers; 
1196         uint32 level = 2;
1197         pstring printername, sharename;
1198         PRINTER_INFO_CTR ctr;
1199
1200         printf("listing printers\n");
1201
1202         if (!get_printer_info(cli, mem_ctx, level, argc, argv, &num_printers, &ctr))
1203                 return nt_status;
1204
1205         for (i = 0; i < num_printers; i++) {
1206
1207                 /* do some initialization */
1208                 rpcstr_pull(printername, ctr.printers_2[i].printername.buffer, 
1209                         sizeof(printername), -1, STR_TERMINATE);
1210                 rpcstr_pull(sharename, ctr.printers_2[i].sharename.buffer, 
1211                         sizeof(sharename), -1, STR_TERMINATE);
1212                 
1213                 d_printf("printer %d: %s, shared as: %s\n", 
1214                         i+1, printername, sharename);
1215         }
1216
1217         return NT_STATUS_OK;
1218 }
1219
1220
1221 /** 
1222  * List printer-drivers from a server 
1223  *
1224  * All parameters are provided by the run_rpc_command function, except for
1225  * argc, argv which are passed through. 
1226  *
1227  * @param domain_sid The domain sid aquired from the remote server
1228  * @param cli A cli_state connected to the server.
1229  * @param mem_ctx Talloc context, destoyed on compleation of the function.
1230  * @param argc  Standard main() style argc
1231  * @param argv  Standard main() style argv.  Initial components are already
1232  *              stripped
1233  *
1234  * @return Normal NTSTATUS return.
1235  **/
1236 NTSTATUS rpc_printer_driver_list_internals(const DOM_SID *domain_sid, const char *domain_name, 
1237                                            struct cli_state *cli, TALLOC_CTX *mem_ctx, 
1238                                            int argc, const char **argv)
1239 {
1240         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1241         uint32 i;
1242         uint32 level = 3; 
1243         PRINTER_DRIVER_CTR drv_ctr_enum;
1244         int d;
1245         
1246         ZERO_STRUCT(drv_ctr_enum);
1247
1248
1249         printf("listing printer-drivers\n");
1250
1251         for (i=0; archi_table[i].long_archi!=NULL; i++) {
1252
1253                 int num_drivers;
1254
1255                 /* enum remote drivers */
1256                 if (!net_spoolss_enumprinterdrivers(cli, mem_ctx, level,
1257                                 archi_table[i].long_archi, 
1258                                 &num_drivers, &drv_ctr_enum)) {
1259                                                                                 
1260                         nt_status = NT_STATUS_UNSUCCESSFUL;
1261                         goto done;
1262                 }
1263
1264                 if (num_drivers == 0) {
1265                         d_printf ("no drivers found on server for architecture: [%s].\n", 
1266                                 archi_table[i].long_archi);
1267                         continue;
1268                 } 
1269                 
1270                 d_printf("got %d printer-drivers for architecture: [%s]\n", 
1271                         num_drivers, archi_table[i].long_archi);
1272
1273
1274                 /* do something for all drivers for architecture */
1275                 for (d = 0; d < num_drivers; d++) {
1276                         display_print_driver_3(&(drv_ctr_enum.info3[d]));
1277                 }
1278         }
1279         
1280         nt_status = NT_STATUS_OK;
1281
1282 done:
1283         return nt_status;
1284
1285 }
1286
1287
1288 /** 
1289  * Migrate Printer-ACLs from a source server to the destination server
1290  *
1291  * All parameters are provided by the run_rpc_command function, except for
1292  * argc, argv which are passed through. 
1293  *
1294  * @param domain_sid The domain sid aquired from the remote server
1295  * @param cli A cli_state connected to the server.
1296  * @param mem_ctx Talloc context, destoyed on compleation of the function.
1297  * @param argc  Standard main() style argc
1298  * @param argv  Standard main() style argv.  Initial components are already
1299  *              stripped
1300  *
1301  * @return Normal NTSTATUS return.
1302  **/
1303 NTSTATUS rpc_printer_migrate_security_internals(const DOM_SID *domain_sid, const char *domain_name, 
1304                                                 struct cli_state *cli, TALLOC_CTX *mem_ctx, 
1305                                                 int argc, const char **argv)
1306 {
1307         /* TODO: what now, info2 or info3 ? 
1308            convince jerry that we should add clientside setacls level 3 at least
1309         */
1310         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1311         uint32 i = 0;
1312         uint32 num_printers;
1313         uint32 level = 2;
1314         fstring servername = "";
1315         pstring printername = "", sharename = "";
1316         BOOL got_hnd_src = False;
1317         BOOL got_hnd_dst = False;
1318         BOOL got_dst_spoolss_pipe = False;
1319         POLICY_HND hnd_src, hnd_dst;
1320         PRINTER_INFO_CTR ctr_src, ctr_dst, ctr_enum;
1321         struct cli_state *cli_dst = NULL;
1322
1323         ZERO_STRUCT(ctr_src);
1324
1325         DEBUG(3,("copying printer ACLs\n"));
1326
1327         /* connect destination PI_SPOOLSS */
1328         nt_status = connect_pipe(&cli_dst, PI_SPOOLSS, &got_dst_spoolss_pipe);
1329         if (!NT_STATUS_IS_OK(nt_status))
1330                 return nt_status;
1331
1332
1333         /* enum source printers */
1334         if (!get_printer_info(cli, mem_ctx, level, argc, argv, &num_printers, &ctr_enum)) {
1335                 nt_status = NT_STATUS_UNSUCCESSFUL;
1336                 goto done;
1337         }
1338
1339         if (!num_printers) {
1340                 printf ("no printers found on server.\n");
1341                 nt_status = NT_STATUS_OK;
1342                 goto done;
1343         } 
1344         
1345
1346         /* do something for all printers */
1347         for (i = 0; i < num_printers; i++) {
1348
1349                 /* do some initialization */
1350                 rpcstr_pull(printername, ctr_enum.printers_2[i].printername.buffer, 
1351                         sizeof(printername), -1, STR_TERMINATE);
1352                 rpcstr_pull(sharename, ctr_enum.printers_2[i].sharename.buffer, 
1353                         sizeof(sharename), -1, STR_TERMINATE);
1354                 /* we can reset NT_STATUS here because we do not 
1355                    get any real NT_STATUS-codes anymore from now on */
1356                 nt_status = NT_STATUS_UNSUCCESSFUL;
1357                 
1358                 d_printf("migrating printer ACLs for:     [%s] / [%s]\n", 
1359                         printername, sharename);
1360
1361                 /* according to msdn you have specify these access-rights 
1362                    to see the security descriptor
1363                         - READ_CONTROL (DACL)
1364                         - ACCESS_SYSTEM_SECURITY (SACL)
1365                 */
1366
1367                 /* open src printer handle */
1368                 if (!net_spoolss_open_printer_ex(cli, mem_ctx, sharename, "", 
1369                         MAXIMUM_ALLOWED_ACCESS, servername, cli->user_name, &hnd_src)) 
1370                         goto done;
1371
1372                 got_hnd_src = True;
1373
1374
1375                 /* open dst printer handle */
1376                 if (!net_spoolss_open_printer_ex(cli_dst, mem_ctx, sharename, "", 
1377                         PRINTER_ALL_ACCESS, servername, cli_dst->user_name, &hnd_dst)) 
1378                         goto done;
1379
1380                 got_hnd_dst = True;
1381
1382
1383                 /* check for existing dst printer */
1384                 if (!net_spoolss_getprinter(cli_dst, mem_ctx, &hnd_dst, level, &ctr_dst)) 
1385                         goto done;
1386
1387                 /* check for existing src printer */
1388                 if (!net_spoolss_getprinter(cli, mem_ctx, &hnd_src, 3, &ctr_src)) 
1389                         goto done;
1390
1391
1392                 /* Copy Security Descriptor */
1393
1394                 /* copy secdesc (info level 2) */
1395                 ctr_dst.printers_2->devmode = NULL; 
1396                 ctr_dst.printers_2->secdesc = dup_sec_desc(mem_ctx, ctr_src.printers_3->secdesc);
1397
1398                 if (opt_verbose)
1399                         display_sec_desc(ctr_dst.printers_2->secdesc);
1400                 
1401                 if (!net_spoolss_setprinter(cli_dst, mem_ctx, &hnd_dst, 2, &ctr_dst)) 
1402                         goto done;
1403                 
1404                 DEBUGADD(1,("\tSetPrinter of SECDESC succeeded\n"));
1405
1406
1407                 /* close printer handles here */
1408                 if (got_hnd_src) {
1409                         cli_spoolss_close_printer(cli, mem_ctx, &hnd_src);
1410                         got_hnd_src = False;
1411                 }
1412
1413                 if (got_hnd_dst) {
1414                         cli_spoolss_close_printer(cli_dst, mem_ctx, &hnd_dst);
1415                         got_hnd_dst = False;
1416                 }
1417
1418         }
1419         
1420         nt_status = NT_STATUS_OK;
1421
1422 done:
1423
1424         if (got_hnd_src)
1425                 cli_spoolss_close_printer(cli, mem_ctx, &hnd_src);
1426
1427         if (got_hnd_dst)
1428                 cli_spoolss_close_printer(cli_dst, mem_ctx, &hnd_dst);
1429
1430         if (got_dst_spoolss_pipe) {
1431                 cli_nt_session_close(cli_dst);
1432                 cli_shutdown(cli_dst);
1433         }
1434         return nt_status;
1435 }
1436
1437
1438 /** 
1439  * Migrate printer-forms from a src server to the dst server
1440  *
1441  * All parameters are provided by the run_rpc_command function, except for
1442  * argc, argv which are passed through. 
1443  *
1444  * @param domain_sid The domain sid aquired from the remote server
1445  * @param cli A cli_state connected to the server.
1446  * @param mem_ctx Talloc context, destoyed on compleation of the function.
1447  * @param argc  Standard main() style argc
1448  * @param argv  Standard main() style argv.  Initial components are already
1449  *              stripped
1450  *
1451  * @return Normal NTSTATUS return.
1452  **/
1453 NTSTATUS rpc_printer_migrate_forms_internals(const DOM_SID *domain_sid, const char *domain_name, 
1454                                              struct cli_state *cli, TALLOC_CTX *mem_ctx, 
1455                                              int argc, const char **argv)
1456 {
1457         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1458         WERROR result;
1459         uint32 i, f;
1460         uint32 num_printers;
1461         uint32 level = 1;
1462         fstring servername = "";
1463         pstring printername = "", sharename = "";
1464         BOOL got_hnd_src = False;
1465         BOOL got_hnd_dst = False;
1466         BOOL got_dst_spoolss_pipe = False;
1467         POLICY_HND hnd_src, hnd_dst;
1468         PRINTER_INFO_CTR ctr_enum, ctr_dst;
1469         uint32 num_forms;
1470         FORM_1 *forms;
1471         struct cli_state *cli_dst = NULL;
1472         
1473         ZERO_STRUCT(ctr_enum);
1474
1475         DEBUG(3,("copying forms\n"));
1476         
1477         /* connect destination PI_SPOOLSS */
1478         nt_status = connect_pipe(&cli_dst, PI_SPOOLSS, &got_dst_spoolss_pipe);
1479         if (!NT_STATUS_IS_OK(nt_status))
1480                 return nt_status;
1481         
1482
1483         /* enum src printers */
1484         if (!get_printer_info(cli, mem_ctx, 2, argc, argv, &num_printers, &ctr_enum)) {
1485                 nt_status = NT_STATUS_UNSUCCESSFUL;
1486                 goto done;
1487         }
1488
1489         if (!num_printers) {
1490                 printf ("no printers found on server.\n");
1491                 nt_status = NT_STATUS_OK;
1492                 goto done;
1493         } 
1494         
1495
1496         /* do something for all printers */
1497         for (i = 0; i < num_printers; i++) {
1498
1499                 /* do some initialization */
1500                 rpcstr_pull(printername, ctr_enum.printers_2[i].printername.buffer, 
1501                         sizeof(printername), -1, STR_TERMINATE);
1502                 rpcstr_pull(sharename, ctr_enum.printers_2[i].sharename.buffer, 
1503                         sizeof(sharename), -1, STR_TERMINATE);
1504                 /* we can reset NT_STATUS here because we do not 
1505                    get any real NT_STATUS-codes anymore from now on */
1506                 nt_status = NT_STATUS_UNSUCCESSFUL;
1507                 
1508                 d_printf("migrating printer forms for:    [%s] / [%s]\n", 
1509                         printername, sharename);
1510
1511
1512                 /* open src printer handle */
1513                 if (!net_spoolss_open_printer_ex(cli, mem_ctx, sharename, "", 
1514                         MAXIMUM_ALLOWED_ACCESS, servername, cli->user_name, &hnd_src)) 
1515                         goto done;
1516
1517                 got_hnd_src = True;
1518
1519
1520                 /* open dst printer handle */
1521                 if (!net_spoolss_open_printer_ex(cli_dst, mem_ctx, sharename, "", 
1522                         PRINTER_ALL_ACCESS, servername, cli->user_name, &hnd_dst)) 
1523                         goto done;
1524
1525                 got_hnd_dst = True;
1526
1527
1528                 /* check for existing dst printer */
1529                 if (!net_spoolss_getprinter(cli_dst, mem_ctx, &hnd_dst, level, &ctr_dst)) 
1530                         goto done;
1531
1532                 /* finally migrate forms */
1533                 if (!net_spoolss_enumforms(cli, mem_ctx, &hnd_src, level, &num_forms, &forms))
1534                         goto done;
1535
1536                 DEBUG(1,("got %d forms for printer\n", num_forms));
1537
1538
1539                 for (f = 0; f < num_forms; f++) {
1540
1541                         FORM form;
1542                         fstring form_name;
1543                         
1544                         /* only migrate FORM_PRINTER types, according to jerry 
1545                            FORM_BUILTIN-types are hard-coded in samba */
1546                         if (forms[f].flag != FORM_PRINTER)
1547                                 continue;
1548
1549                         if (forms[f].name.buffer)
1550                                 rpcstr_pull(form_name, forms[f].name.buffer,
1551                                         sizeof(form_name), -1, STR_TERMINATE);
1552
1553                         if (opt_verbose)
1554                                 d_printf("\tmigrating form # %d [%s] of type [%d]\n", 
1555                                         f, form_name, forms[f].flag);
1556
1557                         /* is there a more elegant way to do that ? */
1558                         form.flags      = FORM_PRINTER;
1559                         form.size_x     = forms[f].width;
1560                         form.size_y     = forms[f].length;
1561                         form.left       = forms[f].left;
1562                         form.top        = forms[f].top;
1563                         form.right      = forms[f].right;
1564                         form.bottom     = forms[f].bottom;
1565                         
1566                         init_unistr2(&form.name, form_name, UNI_STR_TERMINATE);
1567
1568                         /* FIXME: there might be something wrong with samba's 
1569                            builtin-forms */
1570                         result = cli_spoolss_addform(cli_dst, mem_ctx, 
1571                                 &hnd_dst, 1, &form);
1572                         if (!W_ERROR_IS_OK(result)) {
1573                                 d_printf("\tAddForm form %d: [%s] refused.\n", 
1574                                         f, form_name);
1575                                 continue;
1576                         }
1577         
1578                         DEBUGADD(1,("\tAddForm of [%s] succeeded\n", form_name));
1579                 }
1580
1581
1582                 /* close printer handles here */
1583                 if (got_hnd_src) {
1584                         cli_spoolss_close_printer(cli, mem_ctx, &hnd_src);
1585                         got_hnd_src = False;
1586                 }
1587
1588                 if (got_hnd_dst) {
1589                         cli_spoolss_close_printer(cli_dst, mem_ctx, &hnd_dst);
1590                         got_hnd_dst = False;
1591                 }
1592         }
1593
1594         nt_status = NT_STATUS_OK;
1595
1596 done:
1597
1598         if (got_hnd_src)
1599                 cli_spoolss_close_printer(cli, mem_ctx, &hnd_src);
1600
1601         if (got_hnd_dst)
1602                 cli_spoolss_close_printer(cli_dst, mem_ctx, &hnd_dst);
1603
1604         if (got_dst_spoolss_pipe) {
1605                 cli_nt_session_close(cli_dst);
1606                 cli_shutdown(cli_dst);
1607         }
1608         return nt_status;
1609
1610 }
1611
1612
1613 /** 
1614  * Migrate printer-drivers from a src server to the dst server
1615  *
1616  * All parameters are provided by the run_rpc_command function, except for
1617  * argc, argv which are passed through. 
1618  *
1619  * @param domain_sid The domain sid aquired from the remote server
1620  * @param cli A cli_state connected to the server.
1621  * @param mem_ctx Talloc context, destoyed on compleation of the function.
1622  * @param argc  Standard main() style argc
1623  * @param argv  Standard main() style argv.  Initial components are already
1624  *              stripped
1625  *
1626  * @return Normal NTSTATUS return.
1627  **/
1628 NTSTATUS rpc_printer_migrate_drivers_internals(const DOM_SID *domain_sid, const char *domain_name, 
1629                                                struct cli_state *cli, TALLOC_CTX *mem_ctx, 
1630                                                int argc, const char **argv)
1631 {
1632         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1633         uint32 i, p;
1634         uint32 num_printers;
1635         uint32 level = 3; 
1636         fstring servername = "";
1637         pstring printername = "", sharename = "";
1638         BOOL got_hnd_src = False;
1639         BOOL got_hnd_dst = False;
1640         BOOL got_dst_spoolss_pipe = False;
1641         BOOL got_src_driver_share = False;
1642         BOOL got_dst_driver_share = False;
1643         POLICY_HND hnd_src, hnd_dst;
1644         PRINTER_DRIVER_CTR drv_ctr_src, drv_ctr_dst;
1645         PRINTER_INFO_CTR info_ctr_enum, info_ctr_dst;
1646         struct cli_state *cli_dst = NULL;
1647         struct cli_state *cli_share_src = NULL;
1648         struct cli_state *cli_share_dst = NULL;
1649         fstring drivername = "";
1650         
1651         ZERO_STRUCT(drv_ctr_src);
1652         ZERO_STRUCT(drv_ctr_dst);
1653         ZERO_STRUCT(info_ctr_enum);
1654         ZERO_STRUCT(info_ctr_dst);
1655
1656
1657         DEBUG(3,("copying printer-drivers\n"));
1658
1659         nt_status = connect_pipe(&cli_dst, PI_SPOOLSS, &got_dst_spoolss_pipe);
1660         if (!NT_STATUS_IS_OK(nt_status))
1661                 return nt_status;
1662         
1663
1664         /* open print$-share on the src server */
1665         nt_status = connect_to_service(&cli_share_src, &cli->dest_ip, 
1666                         cli->desthost, "print$", "A:");
1667         if (!NT_STATUS_IS_OK(nt_status)) 
1668                 return nt_status;
1669
1670         got_src_driver_share = True;
1671
1672
1673         /* open print$-share on the dst server */
1674         nt_status = connect_to_service(&cli_share_dst, &cli_dst->dest_ip, 
1675                         cli_dst->desthost, "print$", "A:");
1676         if (!NT_STATUS_IS_OK(nt_status)) 
1677                 return nt_status;
1678
1679         got_dst_driver_share = True;
1680
1681
1682         /* enum src printers */
1683         if (!get_printer_info(cli, mem_ctx, 2, argc, argv, &num_printers, &info_ctr_enum)) {
1684                 nt_status = NT_STATUS_UNSUCCESSFUL;
1685                 goto done;
1686         }
1687
1688         if (!num_printers) {
1689                 printf ("no printers found on server.\n");
1690                 nt_status = NT_STATUS_OK;
1691                 goto done;
1692         } 
1693         
1694
1695         /* do something for all printers */
1696         for (p = 0; p < num_printers; p++) {
1697
1698                 /* do some initialization */
1699                 rpcstr_pull(printername, info_ctr_enum.printers_2[p].printername.buffer, 
1700                         sizeof(printername), -1, STR_TERMINATE);
1701                 rpcstr_pull(sharename, info_ctr_enum.printers_2[p].sharename.buffer, 
1702                         sizeof(sharename), -1, STR_TERMINATE);
1703                 /* we can reset NT_STATUS here because we do not 
1704                    get any real NT_STATUS-codes anymore from now on */
1705                 nt_status = NT_STATUS_UNSUCCESSFUL;
1706
1707                 d_printf("migrating printer driver for:   [%s] / [%s]\n", 
1708                         printername, sharename);
1709
1710                 /* open dst printer handle */
1711                 if (!net_spoolss_open_printer_ex(cli_dst, mem_ctx, sharename, "", 
1712                         PRINTER_ALL_ACCESS, servername, cli->user_name, &hnd_dst)) 
1713                         goto done;
1714                         
1715                 got_hnd_dst = True;
1716
1717                 /* check for existing dst printer */
1718                 if (!net_spoolss_getprinter(cli_dst, mem_ctx, &hnd_dst, 2, &info_ctr_dst)) 
1719                         goto done;
1720
1721
1722                 /* open src printer handle */
1723                 if (!net_spoolss_open_printer_ex(cli, mem_ctx, sharename, "", 
1724                         MAXIMUM_ALLOWED_ACCESS, servername, cli->user_name, &hnd_src)) 
1725                         goto done;
1726
1727                 got_hnd_src = True;
1728
1729
1730                 /* in a first step call getdriver for each shared printer (per arch)
1731                    to get a list of all files that have to be copied */
1732                    
1733                 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1734
1735                         /* getdriver src */
1736                         if (!net_spoolss_getprinterdriver(cli, mem_ctx, &hnd_src, 
1737                                         level, archi_table[i].long_archi, 
1738                                         archi_table[i].version, &drv_ctr_src)) 
1739                                 continue;
1740
1741                         rpcstr_pull(drivername, drv_ctr_src.info3->name.buffer, 
1742                                         sizeof(drivername), -1, STR_TERMINATE);
1743
1744                         if (opt_verbose)
1745                                 display_print_driver_3(drv_ctr_src.info3);
1746
1747
1748                         /* check arch dir */
1749                         nt_status = check_arch_dir(cli_share_dst, archi_table[i].short_archi);
1750                         if (!NT_STATUS_IS_OK(nt_status))
1751                                 goto done;
1752
1753
1754                         /* copy driver-files */
1755                         nt_status = copy_print_driver_3(mem_ctx, cli_share_src, cli_share_dst, 
1756                                                         archi_table[i].short_archi, 
1757                                                         drv_ctr_src.info3);
1758                         if (!NT_STATUS_IS_OK(nt_status))
1759                                 goto done;
1760
1761
1762                         /* adddriver dst */
1763                         if (!net_spoolss_addprinterdriver(cli_dst, mem_ctx, level, &drv_ctr_src)) { 
1764                                 nt_status = NT_STATUS_UNSUCCESSFUL;
1765                                 goto done;
1766                         }
1767                                 
1768                         DEBUGADD(1,("Sucessfully added driver [%s] for printer [%s]\n", 
1769                                 drivername, printername));
1770
1771                 }
1772
1773                 /* setdriver dst */
1774                 init_unistr(&info_ctr_dst.printers_2->drivername, drivername);
1775                 
1776                 if (!net_spoolss_setprinter(cli_dst, mem_ctx, &hnd_dst, 2, &info_ctr_dst)) { 
1777                         nt_status = NT_STATUS_UNSUCCESSFUL;
1778                         goto done;
1779                 }
1780
1781                 DEBUGADD(1,("Sucessfully set driver %s for printer %s\n", 
1782                         drivername, printername));
1783
1784                 /* close dst */
1785                 if (got_hnd_dst) {
1786                         cli_spoolss_close_printer(cli_dst, mem_ctx, &hnd_dst);
1787                         got_hnd_dst = False;
1788                 }
1789
1790                 /* close src */
1791                 if (got_hnd_src) {
1792                         cli_spoolss_close_printer(cli, mem_ctx, &hnd_src);
1793                         got_hnd_src = False;
1794                 }
1795         }
1796
1797         nt_status = NT_STATUS_OK;
1798
1799 done:
1800
1801         if (got_hnd_src)
1802                 cli_spoolss_close_printer(cli, mem_ctx, &hnd_src);
1803
1804         if (got_hnd_dst)
1805                 cli_spoolss_close_printer(cli_dst, mem_ctx, &hnd_dst);
1806
1807         if (got_dst_spoolss_pipe) {
1808                 cli_nt_session_close(cli_dst);
1809                 cli_shutdown(cli_dst);
1810         }
1811
1812         if (got_src_driver_share)
1813                 cli_shutdown(cli_share_src);
1814
1815         if (got_dst_driver_share)
1816                 cli_shutdown(cli_share_dst);
1817
1818         return nt_status;
1819
1820 }
1821
1822
1823 /** 
1824  * Migrate printer-queues from a src to the dst server
1825  * (requires a working "addprinter command" to be installed for the local smbd)
1826  *
1827  * All parameters are provided by the run_rpc_command function, except for
1828  * argc, argv which are passed through. 
1829  *
1830  * @param domain_sid The domain sid aquired from the remote server
1831  * @param cli A cli_state connected to the server.
1832  * @param mem_ctx Talloc context, destoyed on compleation of the function.
1833  * @param argc  Standard main() style argc
1834  * @param argv  Standard main() style argv.  Initial components are already
1835  *              stripped
1836  *
1837  * @return Normal NTSTATUS return.
1838  **/
1839 NTSTATUS rpc_printer_migrate_printers_internals(const DOM_SID *domain_sid, const char *domain_name, 
1840                                                 struct cli_state *cli, TALLOC_CTX *mem_ctx, 
1841                                                 int argc, const char **argv)
1842 {
1843         WERROR result;
1844         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1845         uint32 i = 0, num_printers;
1846         uint32 level = 2;
1847         PRINTER_INFO_CTR ctr_src, ctr_dst, ctr_enum;
1848         struct cli_state *cli_dst = NULL;
1849         POLICY_HND hnd_dst, hnd_src;
1850         pstring printername, sharename;
1851         fstring servername;
1852         BOOL got_hnd_src = False;
1853         BOOL got_hnd_dst = False;
1854         BOOL got_dst_spoolss_pipe = False;
1855
1856         DEBUG(3,("copying printers\n"));
1857
1858         /* connect destination PI_SPOOLSS */
1859         nt_status = connect_pipe(&cli_dst, PI_SPOOLSS, &got_dst_spoolss_pipe);
1860         if (!NT_STATUS_IS_OK(nt_status))
1861                 return nt_status;
1862
1863
1864         /* enum printers */
1865         if (!get_printer_info(cli, mem_ctx, 2, argc, argv, &num_printers, &ctr_enum)) {
1866                 nt_status = NT_STATUS_UNSUCCESSFUL;
1867                 goto done;
1868         }
1869
1870         if (!num_printers) {
1871                 printf ("no printers found on server.\n");
1872                 nt_status = NT_STATUS_OK;
1873                 goto done;
1874         } 
1875         
1876
1877         /* do something for all printers */
1878         for (i = 0; i < num_printers; i++) {
1879
1880                 /* do some initialization */
1881                 rpcstr_pull(printername, ctr_enum.printers_2[i].printername.buffer, 
1882                         sizeof(printername), -1, STR_TERMINATE);
1883                 rpcstr_pull(sharename, ctr_enum.printers_2[i].sharename.buffer, 
1884                         sizeof(sharename), -1, STR_TERMINATE);
1885                 /* we can reset NT_STATUS here because we do not 
1886                    get any real NT_STATUS-codes anymore from now on */
1887                 nt_status = NT_STATUS_UNSUCCESSFUL;
1888                 
1889                 d_printf("migrating printer queue for:    [%s] / [%s]\n", 
1890                         printername, sharename);
1891
1892
1893                 /* open dst printer handle */
1894                 if (!net_spoolss_open_printer_ex(cli_dst, mem_ctx, sharename, "", 
1895                         PRINTER_ALL_ACCESS, servername, cli->user_name, &hnd_dst)) {
1896                         
1897                         DEBUG(1,("could not open printer: %s\n", sharename));
1898                 } else {
1899                         got_hnd_dst = True;
1900                 }
1901
1902
1903                 /* check for existing dst printer */
1904                 if (!net_spoolss_getprinter(cli_dst, mem_ctx, &hnd_dst, level, &ctr_dst)) {
1905                         printf ("could not get printer, creating printer.\n");
1906                 } else {
1907                         DEBUG(1,("printer already exists: %s\n", sharename));
1908                         /* close printer handles here */
1909                         if (got_hnd_src) {
1910                                 cli_spoolss_close_printer(cli, mem_ctx, &hnd_src);
1911                                 got_hnd_src = False;
1912                         }
1913
1914                         if (got_hnd_dst) {
1915                                 cli_spoolss_close_printer(cli_dst, mem_ctx, &hnd_dst);
1916                                 got_hnd_dst = False;
1917                         }
1918                         continue;
1919                 }
1920
1921
1922                 /* now get again src printer ctr via getprinter, 
1923                    we first need a handle for that */
1924
1925                 /* open src printer handle */
1926                 if (!net_spoolss_open_printer_ex(cli, mem_ctx, sharename, "", 
1927                         MAXIMUM_ALLOWED_ACCESS, servername, cli->user_name, &hnd_src)) 
1928                         goto done;
1929
1930                 got_hnd_src = True;
1931
1932                 /* getprinter on the src server */
1933                 if (!net_spoolss_getprinter(cli, mem_ctx, &hnd_src, level, &ctr_src)) 
1934                         goto done;
1935
1936
1937                 /* copy each src printer to a dst printer 1:1, 
1938                    maybe some values have to be changed though */
1939                 d_printf("creating printer: %s\n", printername);
1940                 result = cli_spoolss_addprinterex (cli_dst, mem_ctx, level, &ctr_src);
1941
1942                 if (W_ERROR_IS_OK(result))
1943                         d_printf ("printer [%s] successfully added.\n", printername);
1944                 else if (W_ERROR_V(result) == W_ERROR_V(WERR_PRINTER_ALREADY_EXISTS)) 
1945                         d_printf ("printer [%s] already exists.\n", printername);
1946                 else {
1947                         printf ("could not create printer\n");
1948                         goto done;
1949                 }
1950
1951                 /* close printer handles here */
1952                 if (got_hnd_src) {
1953                         cli_spoolss_close_printer(cli, mem_ctx, &hnd_src);
1954                         got_hnd_src = False;
1955                 }
1956
1957                 if (got_hnd_dst) {
1958                         cli_spoolss_close_printer(cli_dst, mem_ctx, &hnd_dst);
1959                         got_hnd_dst = False;
1960                 }
1961         }
1962
1963         nt_status = NT_STATUS_OK;
1964
1965 done:
1966         if (got_hnd_src)
1967                 cli_spoolss_close_printer(cli, mem_ctx, &hnd_src);
1968
1969         if (got_hnd_dst)
1970                 cli_spoolss_close_printer(cli_dst, mem_ctx, &hnd_dst);
1971
1972         if (got_dst_spoolss_pipe) {
1973                 cli_nt_session_close(cli_dst);
1974                 cli_shutdown(cli_dst);
1975         }
1976         return nt_status;
1977 }
1978
1979
1980 /** 
1981  * Migrate Printer-Settings from a src server to the dst server
1982  * (for this to work, printers and drivers already have to be migrated earlier)
1983  *
1984  * All parameters are provided by the run_rpc_command function, except for
1985  * argc, argv which are passed through. 
1986  *
1987  * @param domain_sid The domain sid aquired from the remote server
1988  * @param cli A cli_state connected to the server.
1989  * @param mem_ctx Talloc context, destoyed on compleation of the function.
1990  * @param argc  Standard main() style argc
1991  * @param argv  Standard main() style argv.  Initial components are already
1992  *              stripped
1993  *
1994  * @return Normal NTSTATUS return.
1995  **/
1996 NTSTATUS rpc_printer_migrate_settings_internals(const DOM_SID *domain_sid, const char *domain_name, 
1997                                                 struct cli_state *cli, TALLOC_CTX *mem_ctx, 
1998                                                 int argc, const char **argv)
1999 {
2000
2001         /* FIXME: Here the nightmare begins */
2002
2003         WERROR result;
2004         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
2005         uint32 i = 0, p = 0, j = 0;
2006         uint32 num_printers, val_needed, data_needed;
2007         uint32 level = 2;
2008         fstring servername = "";
2009         pstring printername = "", sharename = "";
2010         BOOL got_hnd_src = False;
2011         BOOL got_hnd_dst = False;
2012         BOOL got_dst_spoolss_pipe = False;
2013         POLICY_HND hnd_src, hnd_dst;
2014         PRINTER_INFO_CTR ctr_enum, ctr_dst;
2015         REGVAL_CTR reg_ctr;
2016         struct cli_state *cli_dst = NULL;
2017         char *devicename = NULL, *unc_name = NULL, *url = NULL;
2018         fstring longname;
2019
2020         const char *keyname = NULL;
2021         uint16 *keylist = NULL, *curkey;
2022
2023         ZERO_STRUCT(ctr_enum);
2024
2025         DEBUG(3,("copying printer settings\n"));
2026
2027         /* connect destination PI_SPOOLSS */
2028         nt_status = connect_pipe(&cli_dst, PI_SPOOLSS, &got_dst_spoolss_pipe);
2029         if (!NT_STATUS_IS_OK(nt_status))
2030                 return nt_status;
2031
2032
2033         /* enum src printers */
2034         if (!get_printer_info(cli, mem_ctx, level, argc, argv, &num_printers, &ctr_enum)) {
2035                 nt_status = NT_STATUS_UNSUCCESSFUL;
2036                 goto done;
2037         }
2038
2039         if (!num_printers) {
2040                 printf ("no printers found on server.\n");
2041                 nt_status = NT_STATUS_OK;
2042                 goto done;
2043         } 
2044         
2045
2046         /* needed for dns-strings in regkeys */
2047         get_mydnsfullname(longname);
2048         
2049         /* do something for all printers */
2050         for (i = 0; i < num_printers; i++) {
2051
2052                 /* do some initialization */
2053                 rpcstr_pull(printername, ctr_enum.printers_2[i].printername.buffer, 
2054                         sizeof(printername), -1, STR_TERMINATE);
2055                 rpcstr_pull(sharename, ctr_enum.printers_2[i].sharename.buffer, 
2056                         sizeof(sharename), -1, STR_TERMINATE);
2057                 keyname = "";
2058                 /* we can reset NT_STATUS here because we do not 
2059                    get any real NT_STATUS-codes anymore from now on */
2060                 nt_status = NT_STATUS_UNSUCCESSFUL;
2061                 
2062                 d_printf("migrating printer settings for: [%s] / [%s]\n", 
2063                         printername, sharename);
2064
2065
2066                 /* open src printer handle */
2067                 if (!net_spoolss_open_printer_ex(cli, mem_ctx, sharename, "", 
2068                         MAXIMUM_ALLOWED_ACCESS, servername, cli->user_name, &hnd_src)) 
2069                         goto done;
2070
2071                 got_hnd_src = True;
2072
2073
2074                 /* open dst printer handle */
2075                 if (!net_spoolss_open_printer_ex(cli_dst, mem_ctx, sharename, "", 
2076                         PRINTER_ALL_ACCESS, servername, cli_dst->user_name, &hnd_dst)) 
2077                         goto done;
2078
2079                 got_hnd_dst = True;
2080
2081
2082                 /* check for existing dst printer */
2083                 if (!net_spoolss_getprinter(cli_dst, mem_ctx, &hnd_dst, 
2084                                 level, &ctr_dst)) 
2085                         goto done;
2086
2087
2088                 /* STEP 1: COPY DEVICE-MODE and other 
2089                            PRINTER_INFO_2-attributes
2090                 */
2091
2092                 ctr_dst.printers_2 = &ctr_enum.printers_2[i];
2093
2094                 /* why is the port always disconnected when the printer 
2095                    is correctly installed (incl. driver ???) */
2096                 init_unistr( &ctr_dst.printers_2->portname, SAMBA_PRINTER_PORT_NAME);
2097
2098                 /* check if printer is published -> no publish-migration for the moment */
2099                 if (ctr_enum.printers_2[i].attributes & PRINTER_ATTRIBUTE_PUBLISHED) {
2100                         printf("printer on originating server was published, ignoring that\n");
2101                         ctr_dst.printers_2->attributes = PRINTER_ATTRIBUTE_SAMBA;
2102                 }
2103
2104                 /* copy devmode (info level 2) */
2105                 ctr_dst.printers_2->devmode = talloc_memdup(mem_ctx, 
2106                         ctr_enum.printers_2[i].devmode, sizeof(DEVICEMODE));
2107
2108                 /* do not copy security descriptor (we have another command for that) */
2109                 ctr_dst.printers_2->secdesc = NULL;
2110
2111
2112                 /* devmode->devicename is possibly broken at the moment for all 
2113                    strlen(longprinternames) > MAXDEVICENAME (that is 32 chars) 
2114                    this fires up thousands of safe_strncpy-debug0-messages 
2115                    on my test-servers
2116                    TODO: tell jerry, jra, etc. again.
2117                 */
2118
2119 #if 0
2120                 if (asprintf(&devicename, "\\\\%s\\%s", longname, printername) < 0) {
2121                         nt_status = NT_STATUS_NO_MEMORY;
2122                         goto done;
2123                 }
2124
2125                 init_unistr(&ctr_dst.printers_2->devmode->devicename, devicename); 
2126 #endif
2127                 if (!net_spoolss_setprinter(cli_dst, mem_ctx, &hnd_dst, 
2128                                                 level, &ctr_dst)) 
2129                         goto done;
2130                 
2131                 DEBUGADD(1,("\tSetPrinter of DEVICEMODE succeeded\n"));
2132
2133
2134
2135                 /* STEP 2: COPY REGISTRY VALUES */
2136         
2137                 /* please keep in mind that samba parse_spools gives horribly 
2138                    crippled results when used to cli_spoolss_enumprinterdataex 
2139                    a win2k3-server.  
2140                    FIXME: IIRC I've seen it too on a win2k-server 
2141                 */
2142
2143                 /* enumerate data on src handle */
2144                 result = cli_spoolss_enumprinterdata(cli, mem_ctx, &hnd_src, p, 0, 0,
2145                         &val_needed, &data_needed, NULL);
2146
2147                 /* loop for all printerdata */
2148                 while (W_ERROR_IS_OK(result)) {
2149                         
2150                         REGISTRY_VALUE value;
2151                         
2152                         result = cli_spoolss_enumprinterdata(
2153                                 cli, mem_ctx, &hnd_src, p++, val_needed,
2154                                 data_needed, 0, 0, &value);
2155
2156                         /* loop for all reg_keys */
2157                         if (W_ERROR_IS_OK(result)) {
2158
2159                                 /* display_value */
2160                                 if (opt_verbose) 
2161                                         display_reg_value(NULL, value);
2162
2163                                 /* set_value */
2164                                 if (!net_spoolss_setprinterdata(cli_dst, mem_ctx, 
2165                                                                 &hnd_dst, &value)) 
2166                                         goto done;
2167
2168                                 DEBUGADD(1,("\tSetPrinterData of [%s] succeeded\n", 
2169                                         value.valuename));
2170                         }
2171                 }
2172                 
2173                 /* STEP 3: COPY SUBKEY VALUES */
2174
2175                 /* here we need to enum all printer_keys and then work 
2176                    on the result with enum_printer_key_ex. nt4 does not
2177                    respond to enumprinterkey, win2k does, so continue 
2178                    in case of an error */
2179
2180                 if (!net_spoolss_enumprinterkey(cli, mem_ctx, &hnd_src, keyname, &keylist)) {
2181                         printf("got no key-data\n");
2182                         continue;
2183                 }
2184
2185
2186                 /* work on a list of printer keys 
2187                    each key has to be enumerated to get all required
2188                    information.  information is then set via setprinterdataex-calls */ 
2189
2190                 if (keylist == NULL)
2191                         continue;
2192
2193                 curkey = keylist;
2194                 while (*curkey != 0) {
2195
2196                         pstring subkey;
2197                         rpcstr_pull(subkey, curkey, sizeof(subkey), -1, STR_TERMINATE);
2198
2199                         curkey += strlen(subkey) + 1;
2200
2201                         /* enumerate all src subkeys */
2202                         if (!net_spoolss_enumprinterdataex(cli, mem_ctx, 0, 
2203                                                            &hnd_src, subkey, 
2204                                                            &reg_ctr)) 
2205                                 goto done;
2206
2207                         for (j=0; j < reg_ctr.num_values; j++) {
2208                         
2209                                 REGISTRY_VALUE value;
2210                                 UNISTR2 data;
2211                         
2212                                 /* although samba replies with sane data in most cases we 
2213                                    should try to avoid writing wrong registry data */
2214         
2215                                 if (strequal(reg_ctr.values[j]->valuename, SPOOL_REG_PORTNAME) || 
2216                                     strequal(reg_ctr.values[j]->valuename, SPOOL_REG_UNCNAME) ||
2217                                     strequal(reg_ctr.values[j]->valuename, SPOOL_REG_URL) ||
2218                                     strequal(reg_ctr.values[j]->valuename, SPOOL_REG_SHORTSERVERNAME) ||
2219                                     strequal(reg_ctr.values[j]->valuename, SPOOL_REG_SERVERNAME)) {
2220
2221                                         if (strequal(reg_ctr.values[j]->valuename, SPOOL_REG_PORTNAME)) {
2222                                 
2223                                                 /* although windows uses a multi-sz, we use a sz */
2224                                                 init_unistr2(&data, SAMBA_PRINTER_PORT_NAME, UNI_STR_TERMINATE);
2225                                                 fstrcpy(value.valuename, SPOOL_REG_PORTNAME);
2226                                         }
2227                                 
2228                                         if (strequal(reg_ctr.values[j]->valuename, SPOOL_REG_UNCNAME)) {
2229                                         
2230                                                 if (asprintf(&unc_name, "\\\\%s\\%s", longname, sharename) < 0) {
2231                                                         nt_status = NT_STATUS_NO_MEMORY;
2232                                                         goto done;
2233                                                 }
2234                                                 init_unistr2(&data, unc_name, UNI_STR_TERMINATE);
2235                                                 fstrcpy(value.valuename, SPOOL_REG_UNCNAME);
2236                                         }
2237
2238                                         if (strequal(reg_ctr.values[j]->valuename, SPOOL_REG_URL)) {
2239
2240                                                 continue;
2241
2242 #if 0
2243                                                 /* FIXME: should we really do that ??? */
2244                                                 if (asprintf(&url, "http://%s:631/printers/%s", longname, sharename) < 0) {
2245                                                         nt_status = NT_STATUS_NO_MEMORY;
2246                                                         goto done;
2247                                                 }
2248                                                 init_unistr2(&data, url, UNI_STR_TERMINATE);
2249                                                 fstrcpy(value.valuename, SPOOL_REG_URL);
2250 #endif
2251                                         }
2252
2253                                         if (strequal(reg_ctr.values[j]->valuename, SPOOL_REG_SERVERNAME)) {
2254
2255                                                 init_unistr2(&data, longname, UNI_STR_TERMINATE);
2256                                                 fstrcpy(value.valuename, SPOOL_REG_SERVERNAME);
2257                                         }
2258
2259                                         if (strequal(reg_ctr.values[j]->valuename, SPOOL_REG_SHORTSERVERNAME)) {
2260
2261                                                 init_unistr2(&data, global_myname(), UNI_STR_TERMINATE);
2262                                                 fstrcpy(value.valuename, SPOOL_REG_SHORTSERVERNAME);
2263                                         }
2264
2265                                         value.type = REG_SZ;
2266                                         value.size = data.uni_str_len * 2;
2267                                         value.data_p = talloc_memdup(mem_ctx, data.buffer, value.size);
2268
2269                                         if (opt_verbose) 
2270                                                 display_reg_value(subkey, value);
2271
2272                                         /* here we have to set all subkeys on the dst server */
2273                                         if (!net_spoolss_setprinterdataex(cli_dst, mem_ctx, &hnd_dst, 
2274                                                         subkey, &value)) 
2275                                                 goto done;
2276                                                         
2277                                 } else {
2278
2279                                         if (opt_verbose) 
2280                                                 display_reg_value(subkey, *(reg_ctr.values[j]));
2281
2282                                         /* here we have to set all subkeys on the dst server */
2283                                         if (!net_spoolss_setprinterdataex(cli_dst, mem_ctx, &hnd_dst, 
2284                                                         subkey, reg_ctr.values[j])) 
2285                                                 goto done;
2286
2287                                 }
2288
2289                                 DEBUGADD(1,("\tSetPrinterDataEx of key [%s\\%s] succeeded\n", 
2290                                                 subkey, reg_ctr.values[j]->valuename));
2291
2292                         }
2293                                                 
2294                         regval_ctr_destroy(&reg_ctr);
2295                 }
2296
2297                 safe_free(keylist);
2298
2299                 /* close printer handles here */
2300                 if (got_hnd_src) {
2301                         cli_spoolss_close_printer(cli, mem_ctx, &hnd_src);
2302                         got_hnd_src = False;
2303                 }
2304
2305                 if (got_hnd_dst) {
2306                         cli_spoolss_close_printer(cli_dst, mem_ctx, &hnd_dst);
2307                         got_hnd_dst = False;
2308                 }
2309
2310         }
2311         
2312         nt_status = NT_STATUS_OK;
2313
2314 done:
2315         SAFE_FREE(devicename);
2316         SAFE_FREE(url);
2317         SAFE_FREE(unc_name);
2318
2319         if (got_hnd_src)
2320                 cli_spoolss_close_printer(cli, mem_ctx, &hnd_src);
2321
2322         if (got_hnd_dst)
2323                 cli_spoolss_close_printer(cli_dst, mem_ctx, &hnd_dst);
2324
2325         if (got_dst_spoolss_pipe) {
2326                 cli_nt_session_close(cli_dst);
2327                 cli_shutdown(cli_dst);
2328         }
2329         return nt_status;
2330 }