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