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