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