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