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