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