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