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