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