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