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