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