c398253616b1bb4815967b532437777438f9fcf5
[vlendec/samba-autobuild/.git] / source3 / utils / net_rpc_printer.c
1 /*
2    Samba Unix/Linux SMB client library
3    Distributed SMB/CIFS Server Management Utility
4    Copyright (C) 2004,2009 Guenther Deschner (gd@samba.org)
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19 #include "includes.h"
20 #include "utils/net.h"
21 #include "../librpc/gen_ndr/cli_spoolss.h"
22 #include "rpc_client/cli_spoolss.h"
23 #include "rpc_client/init_spoolss.h"
24 #include "registry.h"
25 #include "registry/reg_objects.h"
26
27 /* support itanium as well */
28 static const struct print_architecture_table_node archi_table[]= {
29
30         {"Windows 4.0",          "WIN40",       0 },
31         {"Windows NT x86",       "W32X86",      2 },
32         {"Windows NT x86",       "W32X86",      3 },
33         {"Windows NT R4000",     "W32MIPS",     2 },
34         {"Windows NT Alpha_AXP", "W32ALPHA",    2 },
35         {"Windows NT PowerPC",   "W32PPC",      2 },
36         {"Windows IA64",         "IA64",        3 },
37         {"Windows x64",          "x64",         3 },
38         {NULL,                   "",            -1 }
39 };
40
41
42 /**
43  * This display-printdriver-functions was borrowed from rpcclient/cmd_spoolss.c.
44  * It is here for debugging purpose and should be removed later on.
45  **/
46
47 /****************************************************************************
48  Printer info level 3 display function.
49 ****************************************************************************/
50
51 static void display_print_driver3(struct spoolss_DriverInfo3 *r)
52 {
53         int i;
54
55         if (!r) {
56                 return;
57         }
58
59         printf(_("Printer Driver Info 3:\n"));
60         printf(_("\tVersion: [%x]\n"), r->version);
61         printf(_("\tDriver Name: [%s]\n"), r->driver_name);
62         printf(_("\tArchitecture: [%s]\n"), r->architecture);
63         printf(_("\tDriver Path: [%s]\n"), r->driver_path);
64         printf(_("\tDatafile: [%s]\n"), r->data_file);
65         printf(_("\tConfigfile: [%s]\n\n"), r->config_file);
66         printf(_("\tHelpfile: [%s]\n\n"), r->help_file);
67
68         for (i=0; r->dependent_files[i] != NULL; i++) {
69                 printf(_("\tDependentfiles: [%s]\n"), r->dependent_files[i]);
70         }
71
72         printf("\n");
73
74         printf(_("\tMonitorname: [%s]\n"), r->monitor_name);
75         printf(_("\tDefaultdatatype: [%s]\n\n"), r->default_datatype);
76 }
77
78 static void display_reg_value(const char *subkey, struct regval_blob *value)
79 {
80         const char *text;
81         DATA_BLOB blob;
82
83         switch(regval_type(value)) {
84         case REG_DWORD:
85                 d_printf(_("\t[%s:%s]: REG_DWORD: 0x%08x\n"), subkey,
86                         regval_name(value), *((uint32_t *) regval_data_p(value)));
87                 break;
88
89         case REG_SZ:
90                 blob = data_blob_const(regval_data_p(value), regval_size(value));
91                 pull_reg_sz(talloc_tos(), &blob, &text);
92                 if (!text) {
93                         break;
94                 }
95                 d_printf(_("\t[%s:%s]: REG_SZ: %s\n"), subkey, regval_name(value),
96                          text);
97                 break;
98
99         case REG_BINARY:
100                 d_printf(_("\t[%s:%s]: REG_BINARY: unknown length value not "
101                            "displayed\n"),
102                          subkey, regval_name(value));
103                 break;
104
105         case REG_MULTI_SZ: {
106                 uint32_t i;
107                 const char **values;
108                 blob = data_blob_const(regval_data_p(value), regval_size(value));
109
110                 if (!pull_reg_multi_sz(NULL, &blob, &values)) {
111                         d_printf("pull_reg_multi_sz failed\n");
112                         break;
113                 }
114
115                 printf("%s: REG_MULTI_SZ: \n", regval_name(value));
116                 for (i=0; values[i] != NULL; i++) {
117                         d_printf("%s\n", values[i]);
118                 }
119                 TALLOC_FREE(values);
120                 break;
121         }
122
123         default:
124                 d_printf(_("\t%s: unknown type %d\n"), regval_name(value),
125                          regval_type(value));
126         }
127
128 }
129
130 /**
131  * Copies ACLs, DOS-attributes and timestamps from one
132  * file or directory from one connected share to another connected share
133  *
134  * @param c                     A net_context structure
135  * @param mem_ctx               A talloc-context
136  * @param cli_share_src         A connected cli_state
137  * @param cli_share_dst         A connected cli_state
138  * @param src_file              The source file-name
139  * @param dst_file              The destination file-name
140  * @param copy_acls             Whether to copy acls
141  * @param copy_attrs            Whether to copy DOS attributes
142  * @param copy_timestamps       Whether to preserve timestamps
143  * @param is_file               Whether this file is a file or a dir
144  *
145  * @return Normal NTSTATUS return.
146  **/
147
148 NTSTATUS net_copy_fileattr(struct net_context *c,
149                   TALLOC_CTX *mem_ctx,
150                   struct cli_state *cli_share_src,
151                   struct cli_state *cli_share_dst,
152                   const char *src_name, const char *dst_name,
153                   bool copy_acls, bool copy_attrs,
154                   bool copy_timestamps, bool is_file)
155 {
156         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
157         uint16_t fnum_src = 0;
158         uint16_t fnum_dst = 0;
159         struct security_descriptor *sd = NULL;
160         uint16_t attr;
161         time_t f_atime, f_ctime, f_mtime;
162
163
164         if (!copy_timestamps && !copy_acls && !copy_attrs)
165                 return NT_STATUS_OK;
166
167         /* open file/dir on the originating server */
168
169         DEBUGADD(3,("opening %s %s on originating server\n",
170                 is_file?"file":"dir", src_name));
171
172         if (!NT_STATUS_IS_OK(cli_ntcreate(cli_share_src, src_name, 0, READ_CONTROL_ACCESS, 0,
173                                 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0x0, 0x0, &fnum_src))) {
174                 DEBUGADD(0,("cannot open %s %s on originating server %s\n",
175                         is_file?"file":"dir", src_name, cli_errstr(cli_share_src)));
176                 nt_status = cli_nt_error(cli_share_src);
177                 goto out;
178         }
179
180
181         if (copy_acls) {
182
183                 /* get the security descriptor */
184                 sd = cli_query_secdesc(cli_share_src, fnum_src, mem_ctx);
185                 if (!sd) {
186                         DEBUG(0,("failed to get security descriptor: %s\n",
187                                 cli_errstr(cli_share_src)));
188                         nt_status = cli_nt_error(cli_share_src);
189                         goto out;
190                 }
191
192                 if (c->opt_verbose && DEBUGLEVEL >= 3)
193                         display_sec_desc(sd);
194         }
195
196
197         if (copy_attrs || copy_timestamps) {
198
199                 /* get file attributes */
200                 if (!NT_STATUS_IS_OK(cli_getattrE(cli_share_src, fnum_src, &attr, NULL,
201                                  &f_ctime, &f_atime, &f_mtime))) {
202                         DEBUG(0,("failed to get file-attrs: %s\n",
203                                 cli_errstr(cli_share_src)));
204                         nt_status = cli_nt_error(cli_share_src);
205                         goto out;
206                 }
207         }
208
209
210         /* open the file/dir on the destination server */
211
212         if (!NT_STATUS_IS_OK(cli_ntcreate(cli_share_dst, dst_name, 0, WRITE_DAC_ACCESS | WRITE_OWNER_ACCESS, 0,
213                                 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0x0, 0x0, &fnum_dst))) {
214                 DEBUG(0,("failed to open %s on the destination server: %s: %s\n",
215                         is_file?"file":"dir", dst_name, cli_errstr(cli_share_dst)));
216                 nt_status = cli_nt_error(cli_share_dst);
217                 goto out;
218         }
219
220         if (copy_timestamps) {
221
222                 /* set timestamps */
223                 if (!NT_STATUS_IS_OK(cli_setattrE(cli_share_dst, fnum_dst, f_ctime, f_atime, f_mtime))) {
224                         DEBUG(0,("failed to set file-attrs (timestamps): %s\n",
225                                 cli_errstr(cli_share_dst)));
226                         nt_status = cli_nt_error(cli_share_dst);
227                         goto out;
228                 }
229         }
230
231         if (copy_acls) {
232
233                 /* set acls */
234                 if (!cli_set_secdesc(cli_share_dst, fnum_dst, sd)) {
235                         DEBUG(0,("could not set secdesc on %s: %s\n",
236                                 dst_name, cli_errstr(cli_share_dst)));
237                         nt_status = cli_nt_error(cli_share_dst);
238                         goto out;
239                 }
240         }
241
242         if (copy_attrs) {
243
244                 /* set attrs */
245                 if (!NT_STATUS_IS_OK(cli_setatr(cli_share_dst, dst_name, attr, 0))) {
246                         DEBUG(0,("failed to set file-attrs: %s\n",
247                                 cli_errstr(cli_share_dst)));
248                         nt_status = cli_nt_error(cli_share_dst);
249                         goto out;
250                 }
251         }
252
253
254         /* closing files */
255
256         if (!NT_STATUS_IS_OK(cli_close(cli_share_src, fnum_src))) {
257                 d_fprintf(stderr,
258                         _("could not close %s on originating server: %s\n"),
259                         is_file?"file":"dir", cli_errstr(cli_share_src));
260                 nt_status = cli_nt_error(cli_share_src);
261                 goto out;
262         }
263
264         if (!NT_STATUS_IS_OK(cli_close(cli_share_dst, fnum_dst))) {
265                 d_fprintf(stderr,
266                         _("could not close %s on destination server: %s\n"),
267                         is_file?"file":"dir", cli_errstr(cli_share_dst));
268                 nt_status = cli_nt_error(cli_share_dst);
269                 goto out;
270         }
271
272
273         nt_status = NT_STATUS_OK;
274
275 out:
276
277         /* cleaning up */
278         if (fnum_src)
279                 cli_close(cli_share_src, fnum_src);
280
281         if (fnum_dst)
282                 cli_close(cli_share_dst, fnum_dst);
283
284         return nt_status;
285 }
286
287 /**
288  * Copy a file or directory from a connected share to another connected share
289  *
290  * @param c                     A net_context structure
291  * @param mem_ctx               A talloc-context
292  * @param cli_share_src         A connected cli_state
293  * @param cli_share_dst         A connected cli_state
294  * @param src_file              The source file-name
295  * @param dst_file              The destination file-name
296  * @param copy_acls             Whether to copy acls
297  * @param copy_attrs            Whether to copy DOS attributes
298  * @param copy_timestamps       Whether to preserve timestamps
299  * @param is_file               Whether this file is a file or a dir
300  *
301  * @return Normal NTSTATUS return.
302  **/
303
304 NTSTATUS net_copy_file(struct net_context *c,
305                        TALLOC_CTX *mem_ctx,
306                        struct cli_state *cli_share_src,
307                        struct cli_state *cli_share_dst,
308                        const char *src_name, const char *dst_name,
309                        bool copy_acls, bool copy_attrs,
310                        bool copy_timestamps, bool is_file)
311 {
312         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
313         uint16_t fnum_src = 0;
314         uint16_t fnum_dst = 0;
315         static int io_bufsize = 64512;
316         int read_size = io_bufsize;
317         char *data = NULL;
318         off_t nread = 0;
319
320
321         if (!src_name || !dst_name)
322                 goto out;
323
324         if (cli_share_src == NULL || cli_share_dst == NULL)
325                 goto out;
326
327         /* open on the originating server */
328         DEBUGADD(3,("opening %s %s on originating server\n",
329                 is_file ? "file":"dir", src_name));
330         if (is_file)
331                 nt_status = cli_open(cli_share_src, src_name, O_RDONLY, DENY_NONE, &fnum_src);
332         else
333                 nt_status = cli_ntcreate(cli_share_src, src_name, 0, READ_CONTROL_ACCESS, 0,
334                                 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0x0, 0x0, &fnum_src);
335
336         if (!NT_STATUS_IS_OK(nt_status)) {
337                 DEBUGADD(0,("cannot open %s %s on originating server %s\n",
338                         is_file ? "file":"dir",
339                         src_name, cli_errstr(cli_share_src)));
340                 goto out;
341         }
342
343
344         if (is_file) {
345
346                 /* open file on the destination server */
347                 DEBUGADD(3,("opening file %s on destination server\n", dst_name));
348                 nt_status = cli_open(cli_share_dst, dst_name,
349                                 O_RDWR|O_CREAT|O_TRUNC, DENY_NONE, &fnum_dst);
350
351                 if (!NT_STATUS_IS_OK(nt_status)) {
352                         DEBUGADD(1,("cannot create file %s on destination server: %s\n", 
353                                 dst_name, cli_errstr(cli_share_dst)));
354                         goto out;
355                 }
356
357                 /* allocate memory */
358                 if (!(data = (char *)SMB_MALLOC(read_size))) {
359                         d_fprintf(stderr, _("malloc fail for size %d\n"),
360                                   read_size);
361                         nt_status = NT_STATUS_NO_MEMORY;
362                         goto out;
363                 }
364
365         }
366
367
368         if (c->opt_verbose) {
369
370                 d_printf(_("copying [\\\\%s\\%s%s] => [\\\\%s\\%s%s] "
371                            "%s ACLs and %s DOS Attributes %s\n"),
372                         cli_share_src->desthost, cli_share_src->share, src_name,
373                         cli_share_dst->desthost, cli_share_dst->share, dst_name,
374                         copy_acls ?  _("with") : _("without"),
375                         copy_attrs ? _("with") : _("without"),
376                         copy_timestamps ? _("(preserving timestamps)") : "" );
377         }
378
379
380         while (is_file) {
381
382                 /* copying file */
383                 int n, ret;
384                 n = cli_read(cli_share_src, fnum_src, data, nread,
385                                 read_size);
386
387                 if (n <= 0)
388                         break;
389
390                 ret = cli_write(cli_share_dst, fnum_dst, 0, data,
391                         nread, n);
392
393                 if (n != ret) {
394                         d_fprintf(stderr, _("Error writing file: %s\n"),
395                                 cli_errstr(cli_share_dst));
396                         nt_status = cli_nt_error(cli_share_dst);
397                         goto out;
398                 }
399
400                 nread += n;
401         }
402
403
404         if (!is_file && !NT_STATUS_IS_OK(cli_chkpath(cli_share_dst, dst_name))) {
405
406                 /* creating dir */
407                 DEBUGADD(3,("creating dir %s on the destination server\n",
408                         dst_name));
409
410                 if (!NT_STATUS_IS_OK(cli_mkdir(cli_share_dst, dst_name))) {
411                         DEBUG(0,("cannot create directory %s: %s\n",
412                                 dst_name, cli_errstr(cli_share_dst)));
413                         nt_status = NT_STATUS_NO_SUCH_FILE;
414                 }
415
416                 if (!NT_STATUS_IS_OK(cli_chkpath(cli_share_dst, dst_name))) {
417                         d_fprintf(stderr,
418                                 _("cannot check for directory %s: %s\n"),
419                                 dst_name, cli_errstr(cli_share_dst));
420                         goto out;
421                 }
422         }
423
424
425         /* closing files */
426         if (!NT_STATUS_IS_OK(cli_close(cli_share_src, fnum_src))) {
427                 d_fprintf(stderr,
428                         _("could not close file on originating server: %s\n"),
429                         cli_errstr(cli_share_src));
430                 nt_status = cli_nt_error(cli_share_src);
431                 goto out;
432         }
433
434         if (is_file && !NT_STATUS_IS_OK(cli_close(cli_share_dst, fnum_dst))) {
435                 d_fprintf(stderr,
436                         _("could not close file on destination server: %s\n"),
437                         cli_errstr(cli_share_dst));
438                 nt_status = cli_nt_error(cli_share_dst);
439                 goto out;
440         }
441
442         /* possibly we have to copy some file-attributes / acls / sd */
443         nt_status = net_copy_fileattr(c, mem_ctx, cli_share_src, cli_share_dst,
444                                       src_name, dst_name, copy_acls,
445                                       copy_attrs, copy_timestamps, is_file);
446         if (!NT_STATUS_IS_OK(nt_status))
447                 goto out;
448
449
450         nt_status = NT_STATUS_OK;
451
452 out:
453
454         /* cleaning up */
455         if (fnum_src)
456                 cli_close(cli_share_src, fnum_src);
457
458         if (fnum_dst)
459                 cli_close(cli_share_dst, fnum_dst);
460
461         SAFE_FREE(data);
462
463         return nt_status;
464 }
465
466 /**
467  * Copy a driverfile from on connected share to another connected share
468  * This silently assumes that a driver-file is picked up from
469  *
470  *      \\src_server\print$\{arch}\{version}\file
471  *
472  * and copied to
473  *
474  *      \\dst_server\print$\{arch}\file
475  *
476  * to be added via setdriver-calls later.
477  * @param c                     A net_context structure
478  * @param mem_ctx               A talloc-context
479  * @param cli_share_src         A cli_state connected to source print$-share
480  * @param cli_share_dst         A cli_state connected to destination print$-share
481  * @param file                  The file-name to be copied
482  * @param short_archi           The name of the driver-architecture (short form)
483  *
484  * @return Normal NTSTATUS return.
485  **/
486
487 static NTSTATUS net_copy_driverfile(struct net_context *c,
488                                     TALLOC_CTX *mem_ctx,
489                                     struct cli_state *cli_share_src,
490                                     struct cli_state *cli_share_dst,
491                                     const char *file, const char *short_archi) {
492
493         const char *p;
494         char *src_name;
495         char *dst_name;
496         char *version = NULL;
497         char *filename = NULL;
498         char *tok;
499
500         if (!file) {
501                 return NT_STATUS_OK;
502         }
503
504         /* scroll through the file until we have the part
505            beyond archi_table.short_archi */
506         p = file;
507         while (next_token_talloc(mem_ctx, &p, &tok, "\\")) {
508                 if (strequal(tok, short_archi)) {
509                         next_token_talloc(mem_ctx, &p, &version, "\\");
510                         next_token_talloc(mem_ctx, &p, &filename, "\\");
511                 }
512         }
513
514         if (version == NULL || filename == NULL) {
515                 return NT_STATUS_UNSUCCESSFUL;
516         }
517
518         /* build source file name */
519         src_name = talloc_asprintf(mem_ctx, "\\%s\\%s\\%s",
520                                    short_archi, version, filename);
521         if (src_name == NULL) {
522                 return NT_STATUS_NO_MEMORY;
523         }
524
525         /* create destination file name */
526         dst_name = talloc_asprintf(mem_ctx, "\\%s\\%s", short_archi, filename);
527         if (dst_name == NULL) {
528                 return NT_STATUS_NO_MEMORY;
529         }
530
531
532         /* finally copy the file */
533         return net_copy_file(c, mem_ctx, cli_share_src, cli_share_dst,
534                              src_name, dst_name, false, false, false, true);
535 }
536
537 /**
538  * Check for existing Architecture directory on a given server
539  *
540  * @param cli_share             A cli_state connected to a print$-share
541  * @param short_archi           The Architecture for the print-driver
542  *
543  * @return Normal NTSTATUS return.
544  **/
545
546 static NTSTATUS check_arch_dir(struct cli_state *cli_share, const char *short_archi)
547 {
548
549         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
550         char *dir;
551
552         if (asprintf(&dir, "\\%s", short_archi) < 0) {
553                 return NT_STATUS_NO_MEMORY;
554         }
555
556         DEBUG(10,("creating print-driver dir for architecture: %s\n",
557                 short_archi));
558
559         if (!NT_STATUS_IS_OK(cli_mkdir(cli_share, dir))) {
560                 DEBUG(1,("cannot create directory %s: %s\n",
561                          dir, cli_errstr(cli_share)));
562                 nt_status = NT_STATUS_NO_SUCH_FILE;
563         }
564
565         if (!NT_STATUS_IS_OK(cli_chkpath(cli_share, dir))) {
566                 d_fprintf(stderr, _("cannot check %s: %s\n"),
567                         dir, cli_errstr(cli_share));
568                 goto out;
569         }
570
571         nt_status = NT_STATUS_OK;
572
573 out:
574         SAFE_FREE(dir);
575         return nt_status;
576 }
577
578 /**
579  * Copy a print-driver (level 3) from one connected print$-share to another
580  * connected print$-share
581  *
582  * @param c                     A net_context structure
583  * @param mem_ctx               A talloc-context
584  * @param cli_share_src         A cli_state connected to a print$-share
585  * @param cli_share_dst         A cli_state connected to a print$-share
586  * @param short_archi           The Architecture for the print-driver
587  * @param i1                    The DRIVER_INFO_3-struct
588  *
589  * @return Normal NTSTATUS return.
590  **/
591
592 static NTSTATUS copy_print_driver_3(struct net_context *c,
593                     TALLOC_CTX *mem_ctx,
594                     struct cli_state *cli_share_src,
595                     struct cli_state *cli_share_dst,
596                     const char *short_archi,
597                     struct spoolss_DriverInfo3 *r)
598 {
599         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
600         int i;
601
602         if (r == NULL) {
603                 return nt_status;
604         }
605
606         if (c->opt_verbose)
607                 d_printf(_("copying driver: [%s], for architecture: [%s], "
608                            "version: [%d]\n"),
609                           r->driver_name, short_archi, r->version);
610
611         nt_status = net_copy_driverfile(c, mem_ctx, cli_share_src, cli_share_dst,
612                 r->driver_path, short_archi);
613         if (!NT_STATUS_IS_OK(nt_status))
614                 return nt_status;
615
616         nt_status = net_copy_driverfile(c, mem_ctx, cli_share_src, cli_share_dst,
617                 r->data_file, short_archi);
618         if (!NT_STATUS_IS_OK(nt_status))
619                 return nt_status;
620
621         nt_status = net_copy_driverfile(c, mem_ctx, cli_share_src, cli_share_dst,
622                 r->config_file, short_archi);
623         if (!NT_STATUS_IS_OK(nt_status))
624                 return nt_status;
625
626         nt_status = net_copy_driverfile(c, mem_ctx, cli_share_src, cli_share_dst,
627                 r->help_file, short_archi);
628         if (!NT_STATUS_IS_OK(nt_status))
629                 return nt_status;
630
631         for (i=0; r->dependent_files[i] != NULL; i++) {
632
633                 nt_status = net_copy_driverfile(c, mem_ctx,
634                                 cli_share_src, cli_share_dst,
635                                 r->dependent_files[i], short_archi);
636                 if (!NT_STATUS_IS_OK(nt_status)) {
637                         return nt_status;
638                 }
639         }
640
641         return NT_STATUS_OK;
642 }
643
644 /**
645  * net_spoolss-functions
646  * =====================
647  *
648  * the net_spoolss-functions aim to simplify spoolss-client-functions
649  * required during the migration-process wrt buffer-sizes, returned
650  * error-codes, etc.
651  *
652  * this greatly reduces the complexitiy of the migrate-functions.
653  *
654  **/
655
656 static bool net_spoolss_enum_printers(struct rpc_pipe_client *pipe_hnd,
657                                         TALLOC_CTX *mem_ctx,
658                                         char *name,
659                                         uint32_t flags,
660                                         uint32_t level,
661                                         uint32_t *num_printers,
662                                         union spoolss_PrinterInfo **info)
663 {
664         WERROR result;
665
666         /* enum printers */
667
668         result = rpccli_spoolss_enumprinters(pipe_hnd, mem_ctx,
669                                              flags,
670                                              name,
671                                              level,
672                                              0,
673                                              num_printers,
674                                              info);
675         if (!W_ERROR_IS_OK(result)) {
676                 printf(_("cannot enum printers: %s\n"), win_errstr(result));
677                 return false;
678         }
679
680         return true;
681 }
682
683 static bool net_spoolss_open_printer_ex(struct rpc_pipe_client *pipe_hnd,
684                                         TALLOC_CTX *mem_ctx,
685                                         const char *printername,
686                                         uint32_t access_required,
687                                         const char *username,
688                                         struct policy_handle *hnd)
689 {
690         WERROR result;
691         fstring printername2;
692
693         fstrcpy(printername2, pipe_hnd->srv_name_slash);
694         fstrcat(printername2, "\\");
695         fstrcat(printername2, printername);
696
697         DEBUG(10,("connecting to: %s as %s for %s and access: %x\n",
698                 pipe_hnd->srv_name_slash, username, printername2, access_required));
699
700         /* open printer */
701         result = rpccli_spoolss_openprinter_ex(pipe_hnd, mem_ctx,
702                                                printername2,
703                                                access_required,
704                                                hnd);
705
706         /* be more verbose */
707         if (W_ERROR_V(result) == W_ERROR_V(WERR_ACCESS_DENIED)) {
708                 d_fprintf(stderr,
709                         _("no access to printer [%s] on [%s] for user [%s] "
710                           "granted\n"),
711                         printername2, pipe_hnd->srv_name_slash, username);
712                 return false;
713         }
714
715         if (!W_ERROR_IS_OK(result)) {
716                 d_fprintf(stderr,_("cannot open printer %s on server %s: %s\n"),
717                         printername2, pipe_hnd->srv_name_slash, win_errstr(result));
718                 return false;
719         }
720
721         DEBUG(2,("got printer handle for printer: %s, server: %s\n",
722                 printername2, pipe_hnd->srv_name_slash));
723
724         return true;
725 }
726
727 static bool net_spoolss_getprinter(struct rpc_pipe_client *pipe_hnd,
728                                 TALLOC_CTX *mem_ctx,
729                                 struct policy_handle *hnd,
730                                 uint32_t level,
731                                 union spoolss_PrinterInfo *info)
732 {
733         WERROR result;
734
735         /* getprinter call */
736         result = rpccli_spoolss_getprinter(pipe_hnd, mem_ctx,
737                                            hnd,
738                                            level,
739                                            0, /* offered */
740                                            info);
741         if (!W_ERROR_IS_OK(result)) {
742                 printf(_("cannot get printer-info: %s\n"), win_errstr(result));
743                 return false;
744         }
745
746         return true;
747 }
748
749 static bool net_spoolss_setprinter(struct rpc_pipe_client *pipe_hnd,
750                                 TALLOC_CTX *mem_ctx,
751                                 struct policy_handle *hnd,
752                                 uint32_t level,
753                                 union spoolss_PrinterInfo *info)
754 {
755         WERROR result;
756         NTSTATUS status;
757         struct spoolss_SetPrinterInfoCtr info_ctr;
758         struct spoolss_SetPrinterInfo2 info2;
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                 spoolss_printerinfo2_to_setprinterinfo2(&info->info2, &info2);
779                 info_ctr.info.info2 = &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                 struct spoolss_SetPrinterInfo2 info2;
2050
2051                 /* do some initialization */
2052                 printername = info_enum[i].info2.printername;
2053                 sharename = info_enum[i].info2.sharename;
2054
2055                 if (!printername || !sharename) {
2056                         nt_status = NT_STATUS_UNSUCCESSFUL;
2057                         goto done;
2058                 }
2059                 /* we can reset NT_STATUS here because we do not
2060                    get any real NT_STATUS-codes anymore from now on */
2061                 nt_status = NT_STATUS_UNSUCCESSFUL;
2062
2063                 d_printf(_("migrating printer queue for:    [%s] / [%s]\n"),
2064                         printername, sharename);
2065
2066                 /* open dst printer handle */
2067                 if (!net_spoolss_open_printer_ex(pipe_hnd_dst, mem_ctx, sharename,
2068                         PRINTER_ALL_ACCESS, cli->user_name, &hnd_dst)) {
2069
2070                         DEBUG(1,("could not open printer: %s\n", sharename));
2071                 }
2072
2073                 /* check for existing dst printer */
2074                 if (!net_spoolss_getprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, level, &info_dst)) {
2075                         printf (_("could not get printer, creating printer.\n"));
2076                 } else {
2077                         DEBUG(1,("printer already exists: %s\n", sharename));
2078                         /* close printer handle here - dst only, not got src yet. */
2079                         if (is_valid_policy_hnd(&hnd_dst)) {
2080                                 rpccli_spoolss_ClosePrinter(pipe_hnd_dst, mem_ctx, &hnd_dst, NULL);
2081                         }
2082                         continue;
2083                 }
2084
2085                 /* now get again src printer ctr via getprinter,
2086                    we first need a handle for that */
2087
2088                 /* open src printer handle */
2089                 if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, sharename,
2090                         MAXIMUM_ALLOWED_ACCESS, cli->user_name, &hnd_src))
2091                         goto done;
2092
2093                 /* getprinter on the src server */
2094                 if (!net_spoolss_getprinter(pipe_hnd, mem_ctx, &hnd_src, level, &info_src))
2095                         goto done;
2096
2097                 /* copy each src printer to a dst printer 1:1,
2098                    maybe some values have to be changed though */
2099                 d_printf(_("creating printer: %s\n"), printername);
2100
2101                 info_ctr.level = level;
2102                 spoolss_printerinfo2_to_setprinterinfo2(&info_src.info2, &info2);
2103                 info_ctr.info.info2 = &info2;
2104
2105                 result = rpccli_spoolss_addprinterex(pipe_hnd_dst,
2106                                                      mem_ctx,
2107                                                      &info_ctr);
2108
2109                 if (W_ERROR_IS_OK(result))
2110                         d_printf (_("printer [%s] successfully added.\n"),
2111                                   printername);
2112                 else if (W_ERROR_V(result) == W_ERROR_V(WERR_PRINTER_ALREADY_EXISTS))
2113                         d_fprintf (stderr, _("printer [%s] already exists.\n"),
2114                                    printername);
2115                 else {
2116                         d_fprintf (stderr, _("could not create printer [%s]\n"),
2117                                    printername);
2118                         goto done;
2119                 }
2120
2121                 /* close printer handles here */
2122                 if (is_valid_policy_hnd(&hnd_src)) {
2123                         rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd_src, NULL);
2124                 }
2125
2126                 if (is_valid_policy_hnd(&hnd_dst)) {
2127                         rpccli_spoolss_ClosePrinter(pipe_hnd_dst, mem_ctx, &hnd_dst, NULL);
2128                 }
2129         }
2130
2131         nt_status = NT_STATUS_OK;
2132
2133 done:
2134         if (is_valid_policy_hnd(&hnd_src))
2135                 rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd_src, NULL);
2136
2137         if (is_valid_policy_hnd(&hnd_dst))
2138                 rpccli_spoolss_ClosePrinter(pipe_hnd_dst, mem_ctx, &hnd_dst, NULL);
2139
2140         if (cli_dst) {
2141                 cli_shutdown(cli_dst);
2142         }
2143         return nt_status;
2144 }
2145
2146 /**
2147  * Migrate Printer-Settings from a src server to the dst server
2148  * (for this to work, printers and drivers already have to be migrated earlier)
2149  *
2150  * All parameters are provided by the run_rpc_command function, except for
2151  * argc, argv which are passed through.
2152  *
2153  * @param c     A net_context structure
2154  * @param domain_sid The domain sid aquired from the remote server
2155  * @param cli A cli_state connected to the server.
2156  * @param mem_ctx Talloc context, destoyed on compleation of the function.
2157  * @param argc  Standard main() style argc
2158  * @param argv  Standard main() style argv.  Initial components are already
2159  *              stripped
2160  *
2161  * @return Normal NTSTATUS return.
2162  **/
2163
2164 NTSTATUS rpc_printer_migrate_settings_internals(struct net_context *c,
2165                                                 const struct dom_sid *domain_sid,
2166                                                 const char *domain_name,
2167                                                 struct cli_state *cli,
2168                                                 struct rpc_pipe_client *pipe_hnd,
2169                                                 TALLOC_CTX *mem_ctx,
2170                                                 int argc,
2171                                                 const char **argv)
2172 {
2173
2174         /* FIXME: Here the nightmare begins */
2175
2176         WERROR result;
2177         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
2178         uint32_t i = 0, p = 0, j = 0;
2179         uint32_t num_printers;
2180         uint32_t level = 2;
2181         const char *printername, *sharename;
2182         struct rpc_pipe_client *pipe_hnd_dst = NULL;
2183         struct policy_handle hnd_src, hnd_dst;
2184         union spoolss_PrinterInfo *info_enum;
2185         union spoolss_PrinterInfo info_dst_publish;
2186         union spoolss_PrinterInfo info_dst;
2187         struct cli_state *cli_dst = NULL;
2188         char *devicename = NULL, *unc_name = NULL, *url = NULL;
2189         const char *longname;
2190         const char **keylist = NULL;
2191
2192         /* FIXME GD */
2193         ZERO_STRUCT(info_dst_publish);
2194
2195         DEBUG(3,("copying printer settings\n"));
2196
2197         /* connect destination PI_SPOOLSS */
2198         nt_status = connect_dst_pipe(c, &cli_dst, &pipe_hnd_dst,
2199                                      &ndr_table_spoolss.syntax_id);
2200         if (!NT_STATUS_IS_OK(nt_status))
2201                 return nt_status;
2202
2203         /* enum src printers */
2204         if (!get_printer_info(pipe_hnd, mem_ctx, level, argc, argv, &num_printers, &info_enum)) {
2205                 nt_status = NT_STATUS_UNSUCCESSFUL;
2206                 goto done;
2207         }
2208
2209         if (!num_printers) {
2210                 printf (_("no printers found on server.\n"));
2211                 nt_status = NT_STATUS_OK;
2212                 goto done;
2213         }
2214
2215
2216         /* needed for dns-strings in regkeys */
2217         longname = get_mydnsfullname();
2218         if (!longname) {
2219                 nt_status = NT_STATUS_UNSUCCESSFUL;
2220                 goto done;
2221         }
2222
2223         /* do something for all printers */
2224         for (i = 0; i < num_printers; i++) {
2225
2226                 uint32_t value_offered = 0, value_needed;
2227                 uint32_t data_offered = 0, data_needed;
2228                 enum winreg_Type type;
2229                 uint8_t *buffer = NULL;
2230                 const char *value_name = NULL;
2231
2232                 /* do some initialization */
2233                 printername = info_enum[i].info2.printername;
2234                 sharename = info_enum[i].info2.sharename;
2235
2236                 if (!printername || !sharename) {
2237                         nt_status = NT_STATUS_UNSUCCESSFUL;
2238                         goto done;
2239                 }
2240                 /* we can reset NT_STATUS here because we do not
2241                    get any real NT_STATUS-codes anymore from now on */
2242                 nt_status = NT_STATUS_UNSUCCESSFUL;
2243
2244                 d_printf(_("migrating printer settings for: [%s] / [%s]\n"),
2245                         printername, sharename);
2246
2247
2248                 /* open src printer handle */
2249                 if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, sharename,
2250                         MAXIMUM_ALLOWED_ACCESS, cli->user_name, &hnd_src))
2251                         goto done;
2252
2253                 /* open dst printer handle */
2254                 if (!net_spoolss_open_printer_ex(pipe_hnd_dst, mem_ctx, sharename,
2255                         PRINTER_ALL_ACCESS, cli_dst->user_name, &hnd_dst))
2256                         goto done;
2257
2258                 /* check for existing dst printer */
2259                 if (!net_spoolss_getprinter(pipe_hnd_dst, mem_ctx, &hnd_dst,
2260                                 level, &info_dst))
2261                         goto done;
2262
2263
2264                 /* STEP 1: COPY DEVICE-MODE and other
2265                            PRINTER_INFO_2-attributes
2266                 */
2267
2268                 info_dst.info2 = info_enum[i].info2;
2269
2270                 /* why is the port always disconnected when the printer
2271                    is correctly installed (incl. driver ???) */
2272                 info_dst.info2.portname = SAMBA_PRINTER_PORT_NAME;
2273
2274                 /* check if printer is published */
2275                 if (info_enum[i].info2.attributes & PRINTER_ATTRIBUTE_PUBLISHED) {
2276
2277                         /* check for existing dst printer */
2278                         if (!net_spoolss_getprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, 7, &info_dst_publish))
2279                                 goto done;
2280
2281                         info_dst_publish.info7.action = DSPRINT_PUBLISH;
2282
2283                         /* ignore false from setprinter due to WERR_IO_PENDING */
2284                         net_spoolss_setprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, 7, &info_dst_publish);
2285
2286                         DEBUG(3,("republished printer\n"));
2287                 }
2288
2289                 if (info_enum[i].info2.devmode != NULL) {
2290
2291                         /* copy devmode (info level 2) */
2292                         info_dst.info2.devmode = info_enum[i].info2.devmode;
2293
2294                         /* do not copy security descriptor (we have another
2295                          * command for that) */
2296                         info_dst.info2.secdesc = NULL;
2297
2298 #if 0
2299                         info_dst.info2.devmode.devicename =
2300                                 talloc_asprintf(mem_ctx, "\\\\%s\\%s",
2301                                                 longname, printername);
2302                         if (!info_dst.info2.devmode.devicename) {
2303                                 nt_status = NT_STATUS_NO_MEMORY;
2304                                 goto done;
2305                         }
2306 #endif
2307                         if (!net_spoolss_setprinter(pipe_hnd_dst, mem_ctx, &hnd_dst,
2308                                                     level, &info_dst))
2309                                 goto done;
2310
2311                         DEBUGADD(1,("\tSetPrinter of DEVICEMODE succeeded\n"));
2312                 }
2313
2314                 /* STEP 2: COPY REGISTRY VALUES */
2315
2316                 /* please keep in mind that samba parse_spools gives horribly
2317                    crippled results when used to rpccli_spoolss_enumprinterdataex
2318                    a win2k3-server.  (Bugzilla #1851)
2319                    FIXME: IIRC I've seen it too on a win2k-server
2320                 */
2321
2322                 /* enumerate data on src handle */
2323                 nt_status = rpccli_spoolss_EnumPrinterData(pipe_hnd, mem_ctx,
2324                                                            &hnd_src,
2325                                                            p,
2326                                                            value_name,
2327                                                            value_offered,
2328                                                            &value_needed,
2329                                                            &type,
2330                                                            buffer,
2331                                                            data_offered,
2332                                                            &data_needed,
2333                                                            &result);
2334
2335                 data_offered    = data_needed;
2336                 value_offered   = value_needed;
2337                 buffer          = talloc_zero_array(mem_ctx, uint8_t, data_needed);
2338                 value_name      = talloc_zero_array(mem_ctx, char, value_needed);
2339
2340                 /* loop for all printerdata of "PrinterDriverData" */
2341                 while (NT_STATUS_IS_OK(nt_status) && W_ERROR_IS_OK(result)) {
2342
2343                         nt_status = rpccli_spoolss_EnumPrinterData(pipe_hnd, mem_ctx,
2344                                                                    &hnd_src,
2345                                                                    p++,
2346                                                                    value_name,
2347                                                                    value_offered,
2348                                                                    &value_needed,
2349                                                                    &type,
2350                                                                    buffer,
2351                                                                    data_offered,
2352                                                                    &data_needed,
2353                                                                    &result);
2354                         /* loop for all reg_keys */
2355                         if (NT_STATUS_IS_OK(nt_status) && W_ERROR_IS_OK(result)) {
2356
2357                                 /* display_value */
2358                                 if (c->opt_verbose) {
2359                                         struct regval_blob *v;
2360
2361                                         v = regval_compose(talloc_tos(),
2362                                                            value_name,
2363                                                            type,
2364                                                            buffer,
2365                                                            data_offered);
2366                                         if (v == NULL) {
2367                                                 nt_status = NT_STATUS_NO_MEMORY;
2368                                                 goto done;
2369                                         }
2370
2371                                         display_reg_value(SPOOL_PRINTERDATA_KEY, v);
2372                                         talloc_free(v);
2373                                 }
2374
2375                                 /* set_value */
2376                                 if (!net_spoolss_setprinterdata(pipe_hnd_dst, mem_ctx,
2377                                                                 &hnd_dst, value_name,
2378                                                                 type, buffer, data_offered))
2379                                         goto done;
2380
2381                                 DEBUGADD(1,("\tSetPrinterData of [%s] succeeded\n",
2382                                             value_name));
2383                         }
2384                 }
2385
2386                 /* STEP 3: COPY SUBKEY VALUES */
2387
2388                 /* here we need to enum all printer_keys and then work
2389                    on the result with enum_printer_key_ex. nt4 does not
2390                    respond to enumprinterkey, win2k does, so continue
2391                    in case of an error */
2392
2393                 if (!net_spoolss_enumprinterkey(pipe_hnd, mem_ctx, &hnd_src, "", &keylist)) {
2394                         printf(_("got no key-data\n"));
2395                         continue;
2396                 }
2397
2398
2399                 /* work on a list of printer keys
2400                    each key has to be enumerated to get all required
2401                    information.  information is then set via setprinterdataex-calls */
2402
2403                 if (keylist == NULL)
2404                         continue;
2405
2406                 for (i=0; keylist && keylist[i] != NULL; i++) {
2407
2408                         const char *subkey = keylist[i];
2409                         uint32_t count;
2410                         struct spoolss_PrinterEnumValues *info;
2411
2412                         /* enumerate all src subkeys */
2413                         if (!net_spoolss_enumprinterdataex(pipe_hnd, mem_ctx, 0,
2414                                                            &hnd_src, subkey,
2415                                                            &count, &info)) {
2416                                 goto done;
2417                         }
2418
2419                         for (j=0; j < count; j++) {
2420
2421                                 struct regval_blob *value;
2422                                 DATA_BLOB blob;
2423
2424                                 ZERO_STRUCT(blob);
2425
2426                                 /* although samba replies with sane data in most cases we
2427                                    should try to avoid writing wrong registry data */
2428
2429                                 if (strequal(info[j].value_name, SPOOL_REG_PORTNAME) ||
2430                                     strequal(info[j].value_name, SPOOL_REG_UNCNAME) ||
2431                                     strequal(info[j].value_name, SPOOL_REG_URL) ||
2432                                     strequal(info[j].value_name, SPOOL_REG_SHORTSERVERNAME) ||
2433                                     strequal(info[j].value_name, SPOOL_REG_SERVERNAME)) {
2434
2435                                         if (strequal(info[j].value_name, SPOOL_REG_PORTNAME)) {
2436
2437                                                 /* although windows uses a multi-sz, we use a sz */
2438                                                 push_reg_sz(mem_ctx, &blob, SAMBA_PRINTER_PORT_NAME);
2439                                         }
2440
2441                                         if (strequal(info[j].value_name, SPOOL_REG_UNCNAME)) {
2442
2443                                                 if (asprintf(&unc_name, "\\\\%s\\%s", longname, sharename) < 0) {
2444                                                         nt_status = NT_STATUS_NO_MEMORY;
2445                                                         goto done;
2446                                                 }
2447                                                 push_reg_sz(mem_ctx, &blob, unc_name);
2448                                         }
2449
2450                                         if (strequal(info[j].value_name, SPOOL_REG_URL)) {
2451
2452                                                 continue;
2453
2454 #if 0
2455                                                 /* FIXME: should we really do that ??? */
2456                                                 if (asprintf(&url, "http://%s:631/printers/%s", longname, sharename) < 0) {
2457                                                         nt_status = NT_STATUS_NO_MEMORY;
2458                                                         goto done;
2459                                                 }
2460                                                 push_reg_sz(mem_ctx, NULL, &blob, url);
2461                                                 fstrcpy(value.valuename, SPOOL_REG_URL);
2462 #endif
2463                                         }
2464
2465                                         if (strequal(info[j].value_name, SPOOL_REG_SERVERNAME)) {
2466
2467                                                 push_reg_sz(mem_ctx, &blob, longname);
2468                                         }
2469
2470                                         if (strequal(info[j].value_name, SPOOL_REG_SHORTSERVERNAME)) {
2471
2472                                                 push_reg_sz(mem_ctx, &blob, global_myname());
2473                                         }
2474
2475                                         value = regval_compose(talloc_tos(),
2476                                                                info[j].value_name,
2477                                                                REG_SZ,
2478                                                                blob.length == 0 ? NULL : blob.data,
2479                                                                blob.length);
2480                                         if (value == NULL) {
2481                                                 nt_status = NT_STATUS_NO_MEMORY;
2482                                                 goto done;
2483                                         }
2484
2485                                         if (c->opt_verbose)
2486                                                 display_reg_value(subkey, value);
2487
2488                                         /* here we have to set all subkeys on the dst server */
2489                                         if (!net_spoolss_setprinterdataex(pipe_hnd_dst, mem_ctx, &hnd_dst,
2490                                                         subkey, value))
2491                                         {
2492                                                 talloc_free(value);
2493                                                 goto done;
2494                                         }
2495
2496                                         talloc_free(value);
2497                                 } else {
2498
2499                                         struct regval_blob *v;
2500
2501                                         v = regval_compose(talloc_tos(),
2502                                                            info[j].value_name,
2503                                                            info[j].type,
2504                                                            info[j].data->data,
2505                                                            info[j].data->length);
2506                                         if (v == NULL) {
2507                                                 nt_status = NT_STATUS_NO_MEMORY;
2508                                                 goto done;
2509                                         }
2510
2511                                         if (c->opt_verbose) {
2512                                                 display_reg_value(subkey, v);
2513                                         }
2514
2515                                         /* here we have to set all subkeys on the dst server */
2516                                         if (!net_spoolss_setprinterdataex(pipe_hnd_dst, mem_ctx, &hnd_dst,
2517                                                         subkey, v)) {
2518                                                 goto done;
2519                                         }
2520
2521                                         talloc_free(v);
2522                                 }
2523
2524                                 DEBUGADD(1,("\tSetPrinterDataEx of key [%s\\%s] succeeded\n",
2525                                                 subkey, info[j].value_name));
2526
2527                         }
2528                 }
2529
2530                 TALLOC_FREE(keylist);
2531
2532                 /* close printer handles here */
2533                 if (is_valid_policy_hnd(&hnd_src)) {
2534                         rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd_src, NULL);
2535                 }
2536
2537                 if (is_valid_policy_hnd(&hnd_dst)) {
2538                         rpccli_spoolss_ClosePrinter(pipe_hnd_dst, mem_ctx, &hnd_dst, NULL);
2539                 }
2540
2541         }
2542
2543         nt_status = NT_STATUS_OK;
2544
2545 done:
2546         SAFE_FREE(devicename);
2547         SAFE_FREE(url);
2548         SAFE_FREE(unc_name);
2549
2550         if (is_valid_policy_hnd(&hnd_src))
2551                 rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd_src, NULL);
2552
2553         if (is_valid_policy_hnd(&hnd_dst))
2554                 rpccli_spoolss_ClosePrinter(pipe_hnd_dst, mem_ctx, &hnd_dst, NULL);
2555
2556         if (cli_dst) {
2557                 cli_shutdown(cli_dst);
2558         }
2559         return nt_status;
2560 }