s3: use pull_reg_multi_sz in rpcclient and net.
[metze/samba/wip.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
22 /* support itanium as well */
23 static const struct print_architecture_table_node archi_table[]= {
24
25         {"Windows 4.0",          "WIN40",       0 },
26         {"Windows NT x86",       "W32X86",      2 },
27         {"Windows NT x86",       "W32X86",      3 },
28         {"Windows NT R4000",     "W32MIPS",     2 },
29         {"Windows NT Alpha_AXP", "W32ALPHA",    2 },
30         {"Windows NT PowerPC",   "W32PPC",      2 },
31         {"Windows IA64",         "IA64",        3 },
32         {"Windows x64",          "x64",         3 },
33         {NULL,                   "",            -1 }
34 };
35
36
37 /**
38  * This display-printdriver-functions was borrowed from rpcclient/cmd_spoolss.c.
39  * It is here for debugging purpose and should be removed later on.
40  **/
41
42 /****************************************************************************
43  Printer info level 3 display function.
44 ****************************************************************************/
45
46 static void display_print_driver3(struct spoolss_DriverInfo3 *r)
47 {
48         int i;
49
50         if (!r) {
51                 return;
52         }
53
54         printf(_("Printer Driver Info 3:\n"));
55         printf(_("\tVersion: [%x]\n"), r->version);
56         printf(_("\tDriver Name: [%s]\n"), r->driver_name);
57         printf(_("\tArchitecture: [%s]\n"), r->architecture);
58         printf(_("\tDriver Path: [%s]\n"), r->driver_path);
59         printf(_("\tDatafile: [%s]\n"), r->data_file);
60         printf(_("\tConfigfile: [%s]\n\n"), r->config_file);
61         printf(_("\tHelpfile: [%s]\n\n"), r->help_file);
62
63         for (i=0; r->dependent_files[i] != NULL; i++) {
64                 printf(_("\tDependentfiles: [%s]\n"), r->dependent_files[i]);
65         }
66
67         printf("\n");
68
69         printf(_("\tMonitorname: [%s]\n"), r->monitor_name);
70         printf(_("\tDefaultdatatype: [%s]\n\n"), r->default_datatype);
71 }
72
73 static void display_reg_value(const char *subkey, struct regval_blob value)
74 {
75         char *text;
76
77         switch(value.type) {
78         case REG_DWORD:
79                 d_printf(_("\t[%s:%s]: REG_DWORD: 0x%08x\n"), subkey,
80                         value.valuename, *((uint32_t *) value.data_p));
81                 break;
82
83         case REG_SZ:
84                 rpcstr_pull_talloc(talloc_tos(),
85                                 &text,
86                                 value.data_p,
87                                 value.size,
88                                 STR_TERMINATE);
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                 DATA_BLOB 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         SEC_DESC *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                                        union spoolss_PrinterData data)
837 {
838         WERROR result;
839         NTSTATUS status;
840
841         /* setprinterdata call */
842         status = rpccli_spoolss_SetPrinterData(pipe_hnd, mem_ctx,
843                                                hnd,
844                                                value_name,
845                                                type,
846                                                data,
847                                                0, /* autocalculated */
848                                                &result);
849
850         if (!W_ERROR_IS_OK(result)) {
851                 printf (_("unable to set printerdata: %s\n"),
852                         win_errstr(result));
853                 return false;
854         }
855
856         return true;
857 }
858
859
860 static bool net_spoolss_enumprinterkey(struct rpc_pipe_client *pipe_hnd,
861                                         TALLOC_CTX *mem_ctx,
862                                         struct policy_handle *hnd,
863                                         const char *keyname,
864                                         const char ***keylist)
865 {
866         WERROR result;
867
868         /* enumprinterkey call */
869         result = rpccli_spoolss_enumprinterkey(pipe_hnd, mem_ctx, hnd, keyname, keylist, 0);
870
871         if (!W_ERROR_IS_OK(result)) {
872                 printf(_("enumprinterkey failed: %s\n"), win_errstr(result));
873                 return false;
874         }
875
876         return true;
877 }
878
879 static bool net_spoolss_enumprinterdataex(struct rpc_pipe_client *pipe_hnd,
880                                         TALLOC_CTX *mem_ctx,
881                                         uint32_t offered,
882                                         struct policy_handle *hnd,
883                                         const char *keyname,
884                                         uint32_t *count,
885                                         struct spoolss_PrinterEnumValues **info)
886 {
887         WERROR result;
888
889         /* enumprinterdataex call */
890         result = rpccli_spoolss_enumprinterdataex(pipe_hnd, mem_ctx,
891                                                   hnd,
892                                                   keyname,
893                                                   0, /* offered */
894                                                   count,
895                                                   info);
896
897         if (!W_ERROR_IS_OK(result)) {
898                 printf(_("enumprinterdataex failed: %s\n"), win_errstr(result));
899                 return false;
900         }
901
902         return true;
903 }
904
905
906 static bool net_spoolss_setprinterdataex(struct rpc_pipe_client *pipe_hnd,
907                                         TALLOC_CTX *mem_ctx,
908                                         struct policy_handle *hnd,
909                                         const char *keyname,
910                                         struct regval_blob *value)
911 {
912         WERROR result;
913         NTSTATUS status;
914
915         /* setprinterdataex call */
916         status = rpccli_spoolss_SetPrinterDataEx(pipe_hnd, mem_ctx,
917                                                  hnd,
918                                                  keyname,
919                                                  value->valuename,
920                                                  value->type,
921                                                  value->data_p,
922                                                  value->size,
923                                                  &result);
924
925         if (!W_ERROR_IS_OK(result)) {
926                 printf(_("could not set printerdataex: %s\n"),
927                        win_errstr(result));
928                 return false;
929         }
930
931         return true;
932 }
933
934 static bool net_spoolss_enumforms(struct rpc_pipe_client *pipe_hnd,
935                                 TALLOC_CTX *mem_ctx,
936                                 struct policy_handle *hnd,
937                                 int level,
938                                 uint32_t *num_forms,
939                                 union spoolss_FormInfo **forms)
940 {
941         WERROR result;
942
943         /* enumforms call */
944         result = rpccli_spoolss_enumforms(pipe_hnd, mem_ctx,
945                                           hnd,
946                                           level,
947                                           0,
948                                           num_forms,
949                                           forms);
950         if (!W_ERROR_IS_OK(result)) {
951                 printf(_("could not enum forms: %s\n"), win_errstr(result));
952                 return false;
953         }
954
955         return true;
956 }
957
958 static bool net_spoolss_enumprinterdrivers (struct rpc_pipe_client *pipe_hnd,
959                                         TALLOC_CTX *mem_ctx,
960                                         uint32_t level, const char *env,
961                                         uint32_t *count,
962                                         union spoolss_DriverInfo **info)
963 {
964         WERROR result;
965
966         /* enumprinterdrivers call */
967         result = rpccli_spoolss_enumprinterdrivers(pipe_hnd, mem_ctx,
968                                                    pipe_hnd->srv_name_slash,
969                                                    env,
970                                                    level,
971                                                    0,
972                                                    count,
973                                                    info);
974         if (!W_ERROR_IS_OK(result)) {
975                 printf(_("cannot enum drivers: %s\n"), win_errstr(result));
976                 return false;
977         }
978
979         return true;
980 }
981
982 static bool net_spoolss_getprinterdriver(struct rpc_pipe_client *pipe_hnd,
983                              TALLOC_CTX *mem_ctx,
984                              struct policy_handle *hnd, uint32_t level,
985                              const char *env, int version,
986                              union spoolss_DriverInfo *info)
987 {
988         WERROR result;
989         uint32_t server_major_version;
990         uint32_t server_minor_version;
991
992         /* getprinterdriver call */
993         result = rpccli_spoolss_getprinterdriver2(pipe_hnd, mem_ctx,
994                                                   hnd,
995                                                   env,
996                                                   level,
997                                                   0,
998                                                   version,
999                                                   2,
1000                                                   info,
1001                                                   &server_major_version,
1002                                                   &server_minor_version);
1003         if (!W_ERROR_IS_OK(result)) {
1004                 DEBUG(1,("cannot get driver (for architecture: %s): %s\n",
1005                         env, win_errstr(result)));
1006                 if (W_ERROR_V(result) != W_ERROR_V(WERR_UNKNOWN_PRINTER_DRIVER) &&
1007                     W_ERROR_V(result) != W_ERROR_V(WERR_INVALID_ENVIRONMENT)) {
1008                         printf(_("cannot get driver: %s\n"),
1009                                win_errstr(result));
1010                 }
1011                 return false;
1012         }
1013
1014         return true;
1015 }
1016
1017
1018 static bool net_spoolss_addprinterdriver(struct rpc_pipe_client *pipe_hnd,
1019                              TALLOC_CTX *mem_ctx, uint32_t level,
1020                              union spoolss_DriverInfo *info)
1021 {
1022         WERROR result;
1023         NTSTATUS status;
1024         struct spoolss_AddDriverInfoCtr info_ctr;
1025
1026         info_ctr.level = level;
1027
1028         switch (level) {
1029         case 2:
1030                 info_ctr.info.info2 = (struct spoolss_AddDriverInfo2 *)
1031                         (void *)&info->info2;
1032                 break;
1033         case 3:
1034                 info_ctr.info.info3 = (struct spoolss_AddDriverInfo3 *)
1035                         (void *)&info->info3;
1036                 break;
1037         default:
1038                 printf(_("unsupported info level: %d\n"), level);
1039                 return false;
1040         }
1041
1042         /* addprinterdriver call */
1043         status = rpccli_spoolss_AddPrinterDriver(pipe_hnd, mem_ctx,
1044                                                  pipe_hnd->srv_name_slash,
1045                                                  &info_ctr,
1046                                                  &result);
1047         /* be more verbose */
1048         if (W_ERROR_V(result) == W_ERROR_V(WERR_ACCESS_DENIED)) {
1049                 printf(_("You are not allowed to add drivers\n"));
1050                 return false;
1051         }
1052         if (!W_ERROR_IS_OK(result)) {
1053                 printf(_("cannot add driver: %s\n"), win_errstr(result));
1054                 return false;
1055         }
1056
1057         return true;
1058 }
1059
1060 /**
1061  * abstraction function to get uint32_t num_printers and PRINTER_INFO_CTR ctr
1062  * for a single printer or for all printers depending on argc/argv
1063  **/
1064
1065 static bool get_printer_info(struct rpc_pipe_client *pipe_hnd,
1066                         TALLOC_CTX *mem_ctx,
1067                         int level,
1068                         int argc,
1069                         const char **argv,
1070                         uint32_t *num_printers,
1071                         union spoolss_PrinterInfo **info_p)
1072 {
1073         struct policy_handle hnd;
1074
1075         /* no arguments given, enumerate all printers */
1076         if (argc == 0) {
1077
1078                 if (!net_spoolss_enum_printers(pipe_hnd, mem_ctx, NULL,
1079                                 PRINTER_ENUM_LOCAL|PRINTER_ENUM_SHARED,
1080                                 level, num_printers, info_p))
1081                         return false;
1082
1083                 goto out;
1084         }
1085
1086         /* argument given, get a single printer by name */
1087         if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, argv[0],
1088                                          MAXIMUM_ALLOWED_ACCESS,
1089                                          pipe_hnd->auth->user_name,
1090                                          &hnd))
1091                 return false;
1092
1093         if (!net_spoolss_getprinter(pipe_hnd, mem_ctx, &hnd, level, *info_p)) {
1094                 rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd, NULL);
1095                 return false;
1096         }
1097
1098         rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd, NULL);
1099
1100         *num_printers = 1;
1101
1102 out:
1103         DEBUG(3,("got %d printers\n", *num_printers));
1104
1105         return true;
1106
1107 }
1108
1109 /**
1110  * List print-queues (including local printers that are not shared)
1111  *
1112  * All parameters are provided by the run_rpc_command function, except for
1113  * argc, argv which are passed through.
1114  *
1115  * @param c     A net_context structure
1116  * @param domain_sid The domain sid aquired from the remote server
1117  * @param cli A cli_state connected to the server.
1118  * @param mem_ctx Talloc context, destoyed on compleation of the function.
1119  * @param argc  Standard main() style argc
1120  * @param argv  Standard main() style argv.  Initial components are already
1121  *              stripped
1122  *
1123  * @return Normal NTSTATUS return.
1124  **/
1125
1126 NTSTATUS rpc_printer_list_internals(struct net_context *c,
1127                                         const DOM_SID *domain_sid,
1128                                         const char *domain_name,
1129                                         struct cli_state *cli,
1130                                         struct rpc_pipe_client *pipe_hnd,
1131                                         TALLOC_CTX *mem_ctx,
1132                                         int argc,
1133                                         const char **argv)
1134 {
1135         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1136         uint32_t i, num_printers;
1137         uint32_t level = 2;
1138         const char *printername, *sharename;
1139         union spoolss_PrinterInfo *info;
1140
1141         printf("listing printers\n");
1142
1143         if (!get_printer_info(pipe_hnd, mem_ctx, level, argc, argv, &num_printers, &info))
1144                 return nt_status;
1145
1146         for (i = 0; i < num_printers; i++) {
1147
1148                 /* do some initialization */
1149                 printername = info[i].info2.printername;
1150                 sharename = info[i].info2.sharename;
1151
1152                 if (printername && sharename) {
1153                         d_printf(_("printer %d: %s, shared as: %s\n"),
1154                                 i+1, printername, sharename);
1155                 }
1156         }
1157
1158         return NT_STATUS_OK;
1159 }
1160
1161 /**
1162  * List printer-drivers from a server
1163  *
1164  * All parameters are provided by the run_rpc_command function, except for
1165  * argc, argv which are passed through.
1166  *
1167  * @param c     A net_context structure
1168  * @param domain_sid The domain sid aquired from the remote server
1169  * @param cli A cli_state connected to the server.
1170  * @param mem_ctx Talloc context, destoyed on compleation of the function.
1171  * @param argc  Standard main() style argc
1172  * @param argv  Standard main() style argv.  Initial components are already
1173  *              stripped
1174  *
1175  * @return Normal NTSTATUS return.
1176  **/
1177
1178 NTSTATUS rpc_printer_driver_list_internals(struct net_context *c,
1179                                                 const DOM_SID *domain_sid,
1180                                                 const char *domain_name,
1181                                                 struct cli_state *cli,
1182                                                 struct rpc_pipe_client *pipe_hnd,
1183                                                 TALLOC_CTX *mem_ctx,
1184                                                 int argc,
1185                                                 const char **argv)
1186 {
1187         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1188         uint32_t i;
1189         uint32_t level = 3;
1190         union spoolss_DriverInfo *info;
1191         int d;
1192
1193         printf(_("listing printer-drivers\n"));
1194
1195         for (i=0; archi_table[i].long_archi!=NULL; i++) {
1196
1197                 uint32_t num_drivers;
1198
1199                 /* enum remote drivers */
1200                 if (!net_spoolss_enumprinterdrivers(pipe_hnd, mem_ctx, level,
1201                                 archi_table[i].long_archi,
1202                                 &num_drivers, &info)) {
1203                         nt_status = NT_STATUS_UNSUCCESSFUL;
1204                         goto done;
1205                 }
1206
1207                 if (num_drivers == 0) {
1208                         d_printf(_("no drivers found on server for "
1209                                    "architecture: [%s].\n"),
1210                                 archi_table[i].long_archi);
1211                         continue;
1212                 }
1213
1214                 d_printf(_("got %d printer-drivers for architecture: [%s]\n"),
1215                         num_drivers, archi_table[i].long_archi);
1216
1217
1218                 /* do something for all drivers for architecture */
1219                 for (d = 0; d < num_drivers; d++) {
1220                         display_print_driver3(&info[d].info3);
1221                 }
1222         }
1223
1224         nt_status = NT_STATUS_OK;
1225
1226 done:
1227         return nt_status;
1228
1229 }
1230
1231 /**
1232  * Publish print-queues with args-wrapper
1233  *
1234  * @param cli A cli_state connected to the server.
1235  * @param mem_ctx Talloc context, destoyed on compleation of the function.
1236  * @param argc  Standard main() style argc
1237  * @param argv  Standard main() style argv.  Initial components are already
1238  *              stripped
1239  * @param action
1240  *
1241  * @return Normal NTSTATUS return.
1242  **/
1243
1244 static NTSTATUS rpc_printer_publish_internals_args(struct rpc_pipe_client *pipe_hnd,
1245                                         TALLOC_CTX *mem_ctx,
1246                                         int argc,
1247                                         const char **argv,
1248                                         uint32_t action)
1249 {
1250         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1251         uint32_t i, num_printers;
1252         uint32_t level = 7;
1253         const char *printername, *sharename;
1254         union spoolss_PrinterInfo *info_enum;
1255         union spoolss_PrinterInfo info;
1256         struct spoolss_SetPrinterInfoCtr info_ctr;
1257         struct spoolss_DevmodeContainer devmode_ctr;
1258         struct sec_desc_buf secdesc_ctr;
1259         struct policy_handle hnd;
1260         WERROR result;
1261         const char *action_str;
1262
1263         if (!get_printer_info(pipe_hnd, mem_ctx, 2, argc, argv, &num_printers, &info_enum))
1264                 return nt_status;
1265
1266         for (i = 0; i < num_printers; i++) {
1267
1268                 /* do some initialization */
1269                 printername = info_enum[i].info2.printername;
1270                 sharename = info_enum[i].info2.sharename;
1271                 if (!printername || !sharename) {
1272                         goto done;
1273                 }
1274
1275                 /* open printer handle */
1276                 if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, sharename,
1277                         PRINTER_ALL_ACCESS, pipe_hnd->auth->user_name, &hnd))
1278                         goto done;
1279
1280                 /* check for existing dst printer */
1281                 if (!net_spoolss_getprinter(pipe_hnd, mem_ctx, &hnd, level, &info))
1282                         goto done;
1283
1284                 /* check action and set string */
1285                 switch (action) {
1286                 case DSPRINT_PUBLISH:
1287                         action_str = N_("published");
1288                         break;
1289                 case DSPRINT_UPDATE:
1290                         action_str = N_("updated");
1291                         break;
1292                 case DSPRINT_UNPUBLISH:
1293                         action_str = N_("unpublished");
1294                         break;
1295                 default:
1296                         action_str = N_("unknown action");
1297                         printf(_("unkown action: %d\n"), action);
1298                         break;
1299                 }
1300
1301                 info.info7.action = action;
1302                 info_ctr.level = 7;
1303                 info_ctr.info.info7 = (struct spoolss_SetPrinterInfo7 *)
1304                         (void *)&info.info7;
1305
1306                 ZERO_STRUCT(devmode_ctr);
1307                 ZERO_STRUCT(secdesc_ctr);
1308
1309                 nt_status = rpccli_spoolss_SetPrinter(pipe_hnd, mem_ctx,
1310                                                       &hnd,
1311                                                       &info_ctr,
1312                                                       &devmode_ctr,
1313                                                       &secdesc_ctr,
1314                                                       0, /* command */
1315                                                       &result);
1316
1317                 if (!W_ERROR_IS_OK(result) && (W_ERROR_V(result) != W_ERROR_V(WERR_IO_PENDING))) {
1318                         printf(_("cannot set printer-info: %s\n"),
1319                                win_errstr(result));
1320                         goto done;
1321                 }
1322
1323                 printf(_("successfully %s printer %s in Active Directory\n"),
1324                        action_str, sharename);
1325         }
1326
1327         nt_status = NT_STATUS_OK;
1328
1329 done:
1330         if (is_valid_policy_hnd(&hnd))
1331                 rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd, NULL);
1332
1333         return nt_status;
1334 }
1335
1336 NTSTATUS rpc_printer_publish_publish_internals(struct net_context *c,
1337                                                 const DOM_SID *domain_sid,
1338                                                 const char *domain_name,
1339                                                 struct cli_state *cli,
1340                                                 struct rpc_pipe_client *pipe_hnd,
1341                                                 TALLOC_CTX *mem_ctx,
1342                                                 int argc,
1343                                                 const char **argv)
1344 {
1345         return rpc_printer_publish_internals_args(pipe_hnd, mem_ctx, argc, argv, DSPRINT_PUBLISH);
1346 }
1347
1348 NTSTATUS rpc_printer_publish_unpublish_internals(struct net_context *c,
1349                                                 const DOM_SID *domain_sid,
1350                                                 const char *domain_name,
1351                                                 struct cli_state *cli,
1352                                                 struct rpc_pipe_client *pipe_hnd,
1353                                                 TALLOC_CTX *mem_ctx,
1354                                                 int argc,
1355                                                 const char **argv)
1356 {
1357         return rpc_printer_publish_internals_args(pipe_hnd, mem_ctx, argc, argv, DSPRINT_UNPUBLISH);
1358 }
1359
1360 NTSTATUS rpc_printer_publish_update_internals(struct net_context *c,
1361                                                 const DOM_SID *domain_sid,
1362                                                 const char *domain_name,
1363                                                 struct cli_state *cli,
1364                                                 struct rpc_pipe_client *pipe_hnd,
1365                                                 TALLOC_CTX *mem_ctx,
1366                                                 int argc,
1367                                                 const char **argv)
1368 {
1369         return rpc_printer_publish_internals_args(pipe_hnd, mem_ctx, argc, argv, DSPRINT_UPDATE);
1370 }
1371
1372 /**
1373  * List print-queues w.r.t. their publishing state
1374  *
1375  * All parameters are provided by the run_rpc_command function, except for
1376  * argc, argv which are passed through.
1377  *
1378  * @param c     A net_context structure
1379  * @param domain_sid The domain sid aquired from the remote server
1380  * @param cli A cli_state connected to the server.
1381  * @param mem_ctx Talloc context, destoyed on compleation of the function.
1382  * @param argc  Standard main() style argc
1383  * @param argv  Standard main() style argv.  Initial components are already
1384  *              stripped
1385  *
1386  * @return Normal NTSTATUS return.
1387  **/
1388
1389 NTSTATUS rpc_printer_publish_list_internals(struct net_context *c,
1390                                                 const DOM_SID *domain_sid,
1391                                                 const char *domain_name,
1392                                                 struct cli_state *cli,
1393                                                 struct rpc_pipe_client *pipe_hnd,
1394                                                 TALLOC_CTX *mem_ctx,
1395                                                 int argc,
1396                                                 const char **argv)
1397 {
1398         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1399         uint32_t i, num_printers;
1400         uint32_t level = 7;
1401         const char *printername, *sharename;
1402         union spoolss_PrinterInfo *info_enum;
1403         union spoolss_PrinterInfo info;
1404         struct policy_handle hnd;
1405         int state;
1406
1407         if (!get_printer_info(pipe_hnd, mem_ctx, 2, argc, argv, &num_printers, &info_enum))
1408                 return nt_status;
1409
1410         for (i = 0; i < num_printers; i++) {
1411
1412                 /* do some initialization */
1413                 printername = info_enum[i].info2.printername;
1414                 sharename = info_enum[i].info2.sharename;
1415
1416                 if (!printername || !sharename) {
1417                         goto done;
1418                 }
1419
1420                 /* open printer handle */
1421                 if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, sharename,
1422                         PRINTER_ALL_ACCESS, cli->user_name, &hnd))
1423                         goto done;
1424
1425                 /* check for existing dst printer */
1426                 if (!net_spoolss_getprinter(pipe_hnd, mem_ctx, &hnd, level, &info))
1427                         goto done;
1428
1429                 if (!info.info7.guid) {
1430                         goto done;
1431                 }
1432                 state = info.info7.action;
1433                 switch (state) {
1434                         case DSPRINT_PUBLISH:
1435                                 printf(_("printer [%s] is published"),
1436                                        sharename);
1437                                 if (c->opt_verbose)
1438                                         printf(_(", guid: %s"),info.info7.guid);
1439                                 printf("\n");
1440                                 break;
1441                         case DSPRINT_UNPUBLISH:
1442                                 printf(_("printer [%s] is unpublished\n"),
1443                                        sharename);
1444                                 break;
1445                         case DSPRINT_UPDATE:
1446                                 printf(_("printer [%s] is currently updating\n"),
1447                                        sharename);
1448                                 break;
1449                         default:
1450                                 printf(_("unkown state: %d\n"), state);
1451                                 break;
1452                 }
1453         }
1454
1455         nt_status = NT_STATUS_OK;
1456
1457 done:
1458         if (is_valid_policy_hnd(&hnd))
1459                 rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd, NULL);
1460
1461         return nt_status;
1462 }
1463
1464 /**
1465  * Migrate Printer-ACLs from a source server to the destination server
1466  *
1467  * All parameters are provided by the run_rpc_command function, except for
1468  * argc, argv which are passed through.
1469  *
1470  * @param c     A net_context structure
1471  * @param domain_sid The domain sid aquired from the remote server
1472  * @param cli A cli_state connected to the server.
1473  * @param mem_ctx Talloc context, destoyed on compleation of the function.
1474  * @param argc  Standard main() style argc
1475  * @param argv  Standard main() style argv.  Initial components are already
1476  *              stripped
1477  *
1478  * @return Normal NTSTATUS return.
1479  **/
1480
1481 NTSTATUS rpc_printer_migrate_security_internals(struct net_context *c,
1482                                                 const DOM_SID *domain_sid,
1483                                                 const char *domain_name,
1484                                                 struct cli_state *cli,
1485                                                 struct rpc_pipe_client *pipe_hnd,
1486                                                 TALLOC_CTX *mem_ctx,
1487                                                 int argc,
1488                                                 const char **argv)
1489 {
1490         /* TODO: what now, info2 or info3 ?
1491            convince jerry that we should add clientside setacls level 3 at least
1492         */
1493         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1494         uint32_t i = 0;
1495         uint32_t num_printers;
1496         uint32_t level = 2;
1497         const char *printername, *sharename;
1498         struct rpc_pipe_client *pipe_hnd_dst = NULL;
1499         struct policy_handle hnd_src, hnd_dst;
1500         union spoolss_PrinterInfo *info_enum;
1501         struct cli_state *cli_dst = NULL;
1502         union spoolss_PrinterInfo info_src, info_dst;
1503
1504         DEBUG(3,("copying printer ACLs\n"));
1505
1506         /* connect destination PI_SPOOLSS */
1507         nt_status = connect_dst_pipe(c, &cli_dst, &pipe_hnd_dst,
1508                                      &ndr_table_spoolss.syntax_id);
1509         if (!NT_STATUS_IS_OK(nt_status))
1510                 return nt_status;
1511
1512
1513         /* enum source printers */
1514         if (!get_printer_info(pipe_hnd, mem_ctx, level, argc, argv, &num_printers, &info_enum)) {
1515                 nt_status = NT_STATUS_UNSUCCESSFUL;
1516                 goto done;
1517         }
1518
1519         if (!num_printers) {
1520                 printf (_("no printers found on server.\n"));
1521                 nt_status = NT_STATUS_OK;
1522                 goto done;
1523         }
1524
1525         /* do something for all printers */
1526         for (i = 0; i < num_printers; i++) {
1527
1528                 /* do some initialization */
1529                 printername = info_enum[i].info2.printername;
1530                 sharename = info_enum[i].info2.sharename;
1531
1532                 if (!printername || !sharename) {
1533                         nt_status = NT_STATUS_UNSUCCESSFUL;
1534                         goto done;
1535                 }
1536
1537                 /* we can reset NT_STATUS here because we do not
1538                    get any real NT_STATUS-codes anymore from now on */
1539                 nt_status = NT_STATUS_UNSUCCESSFUL;
1540
1541                 d_printf(_("migrating printer ACLs for:     [%s] / [%s]\n"),
1542                         printername, sharename);
1543
1544                 /* according to msdn you have specify these access-rights
1545                    to see the security descriptor
1546                         - READ_CONTROL (DACL)
1547                         - ACCESS_SYSTEM_SECURITY (SACL)
1548                 */
1549
1550                 /* open src printer handle */
1551                 if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, sharename,
1552                         MAXIMUM_ALLOWED_ACCESS, cli->user_name, &hnd_src))
1553                         goto done;
1554
1555                 /* open dst printer handle */
1556                 if (!net_spoolss_open_printer_ex(pipe_hnd_dst, mem_ctx, sharename,
1557                         PRINTER_ALL_ACCESS, cli_dst->user_name, &hnd_dst))
1558                         goto done;
1559
1560                 /* check for existing dst printer */
1561                 if (!net_spoolss_getprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, level, &info_dst))
1562                         goto done;
1563
1564                 /* check for existing src printer */
1565                 if (!net_spoolss_getprinter(pipe_hnd, mem_ctx, &hnd_src, 3, &info_src))
1566                         goto done;
1567
1568                 /* Copy Security Descriptor */
1569
1570                 /* copy secdesc (info level 2) */
1571                 info_dst.info2.devmode = NULL;
1572                 info_dst.info2.secdesc = dup_sec_desc(mem_ctx, info_src.info3.secdesc);
1573
1574                 if (c->opt_verbose)
1575                         display_sec_desc(info_dst.info2.secdesc);
1576
1577                 if (!net_spoolss_setprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, 2, &info_dst))
1578                         goto done;
1579
1580                 DEBUGADD(1,("\tSetPrinter of SECDESC succeeded\n"));
1581
1582
1583                 /* close printer handles here */
1584                 if (is_valid_policy_hnd(&hnd_src)) {
1585                         rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd_src, NULL);
1586                 }
1587
1588                 if (is_valid_policy_hnd(&hnd_dst)) {
1589                         rpccli_spoolss_ClosePrinter(pipe_hnd_dst, mem_ctx, &hnd_dst, NULL);
1590                 }
1591
1592         }
1593
1594         nt_status = NT_STATUS_OK;
1595
1596 done:
1597
1598         if (is_valid_policy_hnd(&hnd_src)) {
1599                 rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd_src, NULL);
1600         }
1601
1602         if (is_valid_policy_hnd(&hnd_dst)) {
1603                 rpccli_spoolss_ClosePrinter(pipe_hnd_dst, mem_ctx, &hnd_dst, NULL);
1604         }
1605
1606         if (cli_dst) {
1607                 cli_shutdown(cli_dst);
1608         }
1609         return nt_status;
1610 }
1611
1612 /**
1613  * Migrate printer-forms from a src server to the dst server
1614  *
1615  * All parameters are provided by the run_rpc_command function, except for
1616  * argc, argv which are passed through.
1617  *
1618  * @param c     A net_context structure
1619  * @param domain_sid The domain sid aquired from the remote server
1620  * @param cli A cli_state connected to the server.
1621  * @param mem_ctx Talloc context, destoyed on compleation of the function.
1622  * @param argc  Standard main() style argc
1623  * @param argv  Standard main() style argv.  Initial components are already
1624  *              stripped
1625  *
1626  * @return Normal NTSTATUS return.
1627  **/
1628
1629 NTSTATUS rpc_printer_migrate_forms_internals(struct net_context *c,
1630                                                 const DOM_SID *domain_sid,
1631                                                 const char *domain_name,
1632                                                 struct cli_state *cli,
1633                                                 struct rpc_pipe_client *pipe_hnd,
1634                                                 TALLOC_CTX *mem_ctx,
1635                                                 int argc,
1636                                                 const char **argv)
1637 {
1638         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1639         WERROR result;
1640         uint32_t i, f;
1641         uint32_t num_printers;
1642         uint32_t level = 1;
1643         const char *printername, *sharename;
1644         struct rpc_pipe_client *pipe_hnd_dst = NULL;
1645         struct policy_handle hnd_src, hnd_dst;
1646         union spoolss_PrinterInfo *info_enum;
1647         union spoolss_PrinterInfo info_dst;
1648         uint32_t num_forms;
1649         union spoolss_FormInfo *forms;
1650         struct cli_state *cli_dst = NULL;
1651
1652         DEBUG(3,("copying forms\n"));
1653
1654         /* connect destination PI_SPOOLSS */
1655         nt_status = connect_dst_pipe(c, &cli_dst, &pipe_hnd_dst,
1656                                      &ndr_table_spoolss.syntax_id);
1657         if (!NT_STATUS_IS_OK(nt_status))
1658                 return nt_status;
1659
1660         /* enum src printers */
1661         if (!get_printer_info(pipe_hnd, mem_ctx, 2, argc, argv, &num_printers, &info_enum)) {
1662                 nt_status = NT_STATUS_UNSUCCESSFUL;
1663                 goto done;
1664         }
1665
1666         if (!num_printers) {
1667                 printf (_("no printers found on server.\n"));
1668                 nt_status = NT_STATUS_OK;
1669                 goto done;
1670         }
1671
1672         /* do something for all printers */
1673         for (i = 0; i < num_printers; i++) {
1674
1675                 /* do some initialization */
1676                 printername = info_enum[i].info2.printername;
1677                 sharename = info_enum[i].info2.sharename;
1678
1679                 if (!printername || !sharename) {
1680                         nt_status = NT_STATUS_UNSUCCESSFUL;
1681                         goto done;
1682                 }
1683                 /* we can reset NT_STATUS here because we do not
1684                    get any real NT_STATUS-codes anymore from now on */
1685                 nt_status = NT_STATUS_UNSUCCESSFUL;
1686
1687                 d_printf(_("migrating printer forms for:    [%s] / [%s]\n"),
1688                         printername, sharename);
1689
1690
1691                 /* open src printer handle */
1692                 if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, sharename,
1693                         MAXIMUM_ALLOWED_ACCESS, cli->user_name, &hnd_src))
1694                         goto done;
1695
1696                 /* open dst printer handle */
1697                 if (!net_spoolss_open_printer_ex(pipe_hnd_dst, mem_ctx, sharename,
1698                         PRINTER_ALL_ACCESS, cli->user_name, &hnd_dst))
1699                         goto done;
1700
1701                 /* check for existing dst printer */
1702                 if (!net_spoolss_getprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, level, &info_dst))
1703                         goto done;
1704
1705                 /* finally migrate forms */
1706                 if (!net_spoolss_enumforms(pipe_hnd, mem_ctx, &hnd_src, level, &num_forms, &forms))
1707                         goto done;
1708
1709                 DEBUG(1,("got %d forms for printer\n", num_forms));
1710
1711
1712                 for (f = 0; f < num_forms; f++) {
1713
1714                         union spoolss_AddFormInfo info;
1715                         NTSTATUS status;
1716
1717                         /* only migrate FORM_PRINTER types, according to jerry
1718                            FORM_BUILTIN-types are hard-coded in samba */
1719                         if (forms[f].info1.flags != SPOOLSS_FORM_PRINTER)
1720                                 continue;
1721
1722                         if (c->opt_verbose)
1723                                 d_printf(_("\tmigrating form # %d [%s] of type "
1724                                            "[%d]\n"),
1725                                         f, forms[f].info1.form_name,
1726                                         forms[f].info1.flags);
1727
1728                         info.info1 = (struct spoolss_AddFormInfo1 *)
1729                                 (void *)&forms[f].info1;
1730
1731                         /* FIXME: there might be something wrong with samba's
1732                            builtin-forms */
1733                         status = rpccli_spoolss_AddForm(pipe_hnd_dst, mem_ctx,
1734                                                         &hnd_dst,
1735                                                         1,
1736                                                         info,
1737                                                         &result);
1738                         if (!W_ERROR_IS_OK(result)) {
1739                                 d_printf(_("\tAddForm form %d: [%s] refused.\n"),
1740                                         f, forms[f].info1.form_name);
1741                                 continue;
1742                         }
1743
1744                         DEBUGADD(1,("\tAddForm of [%s] succeeded\n",
1745                                 forms[f].info1.form_name));
1746                 }
1747
1748
1749                 /* close printer handles here */
1750                 if (is_valid_policy_hnd(&hnd_src)) {
1751                         rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd_src, NULL);
1752                 }
1753
1754                 if (is_valid_policy_hnd(&hnd_dst)) {
1755                         rpccli_spoolss_ClosePrinter(pipe_hnd_dst, mem_ctx, &hnd_dst, NULL);
1756                 }
1757         }
1758
1759         nt_status = NT_STATUS_OK;
1760
1761 done:
1762
1763         if (is_valid_policy_hnd(&hnd_src))
1764                 rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd_src, NULL);
1765
1766         if (is_valid_policy_hnd(&hnd_dst))
1767                 rpccli_spoolss_ClosePrinter(pipe_hnd_dst, mem_ctx, &hnd_dst, NULL);
1768
1769         if (cli_dst) {
1770                 cli_shutdown(cli_dst);
1771         }
1772         return nt_status;
1773 }
1774
1775 /**
1776  * Migrate printer-drivers from a src server to the dst server
1777  *
1778  * All parameters are provided by the run_rpc_command function, except for
1779  * argc, argv which are passed through.
1780  *
1781  * @param c     A net_context structure
1782  * @param domain_sid The domain sid aquired from the remote server
1783  * @param cli A cli_state connected to the server.
1784  * @param mem_ctx Talloc context, destoyed on compleation of the function.
1785  * @param argc  Standard main() style argc
1786  * @param argv  Standard main() style argv.  Initial components are already
1787  *              stripped
1788  *
1789  * @return Normal NTSTATUS return.
1790  **/
1791
1792 NTSTATUS rpc_printer_migrate_drivers_internals(struct net_context *c,
1793                                                 const DOM_SID *domain_sid,
1794                                                 const char *domain_name,
1795                                                 struct cli_state *cli,
1796                                                 struct rpc_pipe_client *pipe_hnd,
1797                                                 TALLOC_CTX *mem_ctx,
1798                                                 int argc,
1799                                                 const char **argv)
1800 {
1801         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1802         uint32_t i, p;
1803         uint32_t num_printers;
1804         uint32_t level = 3;
1805         const char *printername, *sharename;
1806         bool got_src_driver_share = false;
1807         bool got_dst_driver_share = false;
1808         struct rpc_pipe_client *pipe_hnd_dst = NULL;
1809         struct policy_handle hnd_src, hnd_dst;
1810         union spoolss_DriverInfo drv_info_src;
1811         union spoolss_PrinterInfo *info_enum;
1812         union spoolss_PrinterInfo info_dst;
1813         struct cli_state *cli_dst = NULL;
1814         struct cli_state *cli_share_src = NULL;
1815         struct cli_state *cli_share_dst = NULL;
1816         const char *drivername = NULL;
1817
1818         DEBUG(3,("copying printer-drivers\n"));
1819
1820         nt_status = connect_dst_pipe(c, &cli_dst, &pipe_hnd_dst,
1821                                      &ndr_table_spoolss.syntax_id);
1822         if (!NT_STATUS_IS_OK(nt_status))
1823                 return nt_status;
1824
1825         /* open print$-share on the src server */
1826         nt_status = connect_to_service(c, &cli_share_src, &cli->dest_ss,
1827                         cli->desthost, "print$", "A:");
1828         if (!NT_STATUS_IS_OK(nt_status))
1829                 goto done;
1830
1831         got_src_driver_share = true;
1832
1833
1834         /* open print$-share on the dst server */
1835         nt_status = connect_to_service(c, &cli_share_dst, &cli_dst->dest_ss,
1836                         cli_dst->desthost, "print$", "A:");
1837         if (!NT_STATUS_IS_OK(nt_status))
1838                 return nt_status;
1839
1840         got_dst_driver_share = true;
1841
1842
1843         /* enum src printers */
1844         if (!get_printer_info(pipe_hnd, mem_ctx, 2, argc, argv, &num_printers, &info_enum)) {
1845                 nt_status = NT_STATUS_UNSUCCESSFUL;
1846                 goto done;
1847         }
1848
1849         if (num_printers == 0) {
1850                 printf (_("no printers found on server.\n"));
1851                 nt_status = NT_STATUS_OK;
1852                 goto done;
1853         }
1854
1855
1856         /* do something for all printers */
1857         for (p = 0; p < num_printers; p++) {
1858
1859                 /* do some initialization */
1860                 printername = info_enum[p].info2.printername;
1861                 sharename = info_enum[p].info2.sharename;
1862
1863                 if (!printername || !sharename) {
1864                         nt_status = NT_STATUS_UNSUCCESSFUL;
1865                         goto done;
1866                 }
1867
1868                 /* we can reset NT_STATUS here because we do not
1869                    get any real NT_STATUS-codes anymore from now on */
1870                 nt_status = NT_STATUS_UNSUCCESSFUL;
1871
1872                 d_printf(_("migrating printer driver for:   [%s] / [%s]\n"),
1873                         printername, sharename);
1874
1875                 /* open dst printer handle */
1876                 if (!net_spoolss_open_printer_ex(pipe_hnd_dst, mem_ctx, sharename,
1877                         PRINTER_ALL_ACCESS, cli->user_name, &hnd_dst))
1878                         goto done;
1879
1880                 /* check for existing dst printer */
1881                 if (!net_spoolss_getprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, 2, &info_dst))
1882                         goto done;
1883
1884
1885                 /* open src printer handle */
1886                 if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, sharename,
1887                                                  MAXIMUM_ALLOWED_ACCESS,
1888                                                  pipe_hnd->auth->user_name,
1889                                                  &hnd_src))
1890                         goto done;
1891
1892                 /* in a first step call getdriver for each shared printer (per arch)
1893                    to get a list of all files that have to be copied */
1894
1895                 for (i=0; archi_table[i].long_archi!=NULL; i++) {
1896
1897                         /* getdriver src */
1898                         if (!net_spoolss_getprinterdriver(pipe_hnd, mem_ctx, &hnd_src,
1899                                         level, archi_table[i].long_archi,
1900                                         archi_table[i].version, &drv_info_src))
1901                                 continue;
1902
1903                         drivername = drv_info_src.info3.driver_name;
1904
1905                         if (c->opt_verbose)
1906                                 display_print_driver3(&drv_info_src.info3);
1907
1908                         /* check arch dir */
1909                         nt_status = check_arch_dir(cli_share_dst, archi_table[i].short_archi);
1910                         if (!NT_STATUS_IS_OK(nt_status))
1911                                 goto done;
1912
1913
1914                         /* copy driver-files */
1915                         nt_status = copy_print_driver_3(c, mem_ctx, cli_share_src, cli_share_dst,
1916                                                         archi_table[i].short_archi,
1917                                                         &drv_info_src.info3);
1918                         if (!NT_STATUS_IS_OK(nt_status))
1919                                 goto done;
1920
1921
1922                         /* adddriver dst */
1923                         if (!net_spoolss_addprinterdriver(pipe_hnd_dst, mem_ctx, level, &drv_info_src)) {
1924                                 nt_status = NT_STATUS_UNSUCCESSFUL;
1925                                 goto done;
1926                         }
1927
1928                         DEBUGADD(1,("Sucessfully added driver [%s] for printer [%s]\n",
1929                                 drivername, printername));
1930
1931                 }
1932
1933                 if (!drivername || strlen(drivername) == 0) {
1934                         DEBUGADD(1,("Did not get driver for printer %s\n",
1935                                     printername));
1936                         goto done;
1937                 }
1938
1939                 /* setdriver dst */
1940                 info_dst.info2.drivername = drivername;
1941
1942                 if (!net_spoolss_setprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, 2, &info_dst)) {
1943                         nt_status = NT_STATUS_UNSUCCESSFUL;
1944                         goto done;
1945                 }
1946
1947                 DEBUGADD(1,("Sucessfully set driver %s for printer %s\n",
1948                         drivername, printername));
1949
1950                 /* close dst */
1951                 if (is_valid_policy_hnd(&hnd_dst)) {
1952                         rpccli_spoolss_ClosePrinter(pipe_hnd_dst, mem_ctx, &hnd_dst, NULL);
1953                 }
1954
1955                 /* close src */
1956                 if (is_valid_policy_hnd(&hnd_src)) {
1957                         rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd_src, NULL);
1958                 }
1959         }
1960
1961         nt_status = NT_STATUS_OK;
1962
1963 done:
1964
1965         if (is_valid_policy_hnd(&hnd_src))
1966                 rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd_src, NULL);
1967
1968         if (is_valid_policy_hnd(&hnd_dst))
1969                 rpccli_spoolss_ClosePrinter(pipe_hnd_dst, mem_ctx, &hnd_dst, NULL);
1970
1971         if (cli_dst) {
1972                 cli_shutdown(cli_dst);
1973         }
1974
1975         if (got_src_driver_share)
1976                 cli_shutdown(cli_share_src);
1977
1978         if (got_dst_driver_share)
1979                 cli_shutdown(cli_share_dst);
1980
1981         return nt_status;
1982
1983 }
1984
1985 /**
1986  * Migrate printer-queues from a src to the dst server
1987  * (requires a working "addprinter command" to be installed for the local smbd)
1988  *
1989  * All parameters are provided by the run_rpc_command function, except for
1990  * argc, argv which are passed through.
1991  *
1992  * @param c     A net_context structure
1993  * @param domain_sid The domain sid aquired from the remote server
1994  * @param cli A cli_state connected to the server.
1995  * @param mem_ctx Talloc context, destoyed on compleation of the function.
1996  * @param argc  Standard main() style argc
1997  * @param argv  Standard main() style argv.  Initial components are already
1998  *              stripped
1999  *
2000  * @return Normal NTSTATUS return.
2001  **/
2002
2003 NTSTATUS rpc_printer_migrate_printers_internals(struct net_context *c,
2004                                                 const DOM_SID *domain_sid,
2005                                                 const char *domain_name,
2006                                                 struct cli_state *cli,
2007                                                 struct rpc_pipe_client *pipe_hnd,
2008                                                 TALLOC_CTX *mem_ctx,
2009                                                 int argc,
2010                                                 const char **argv)
2011 {
2012         WERROR result;
2013         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
2014         uint32_t i = 0, num_printers;
2015         uint32_t level = 2;
2016         union spoolss_PrinterInfo info_dst, info_src;
2017         union spoolss_PrinterInfo *info_enum;
2018         struct cli_state *cli_dst = NULL;
2019         struct policy_handle hnd_dst, hnd_src;
2020         const char *printername, *sharename;
2021         struct rpc_pipe_client *pipe_hnd_dst = NULL;
2022         struct spoolss_SetPrinterInfoCtr info_ctr;
2023
2024         DEBUG(3,("copying printers\n"));
2025
2026         /* connect destination PI_SPOOLSS */
2027         nt_status = connect_dst_pipe(c, &cli_dst, &pipe_hnd_dst,
2028                                      &ndr_table_spoolss.syntax_id);
2029         if (!NT_STATUS_IS_OK(nt_status))
2030                 return nt_status;
2031
2032         /* enum printers */
2033         if (!get_printer_info(pipe_hnd, mem_ctx, level, argc, argv, &num_printers, &info_enum)) {
2034                 nt_status = NT_STATUS_UNSUCCESSFUL;
2035                 goto done;
2036         }
2037
2038         if (!num_printers) {
2039                 printf (_("no printers found on server.\n"));
2040                 nt_status = NT_STATUS_OK;
2041                 goto done;
2042         }
2043
2044         /* do something for all printers */
2045         for (i = 0; i < num_printers; i++) {
2046
2047                 /* do some initialization */
2048                 printername = info_enum[i].info2.printername;
2049                 sharename = info_enum[i].info2.sharename;
2050
2051                 if (!printername || !sharename) {
2052                         nt_status = NT_STATUS_UNSUCCESSFUL;
2053                         goto done;
2054                 }
2055                 /* we can reset NT_STATUS here because we do not
2056                    get any real NT_STATUS-codes anymore from now on */
2057                 nt_status = NT_STATUS_UNSUCCESSFUL;
2058
2059                 d_printf(_("migrating printer queue for:    [%s] / [%s]\n"),
2060                         printername, sharename);
2061
2062                 /* open dst printer handle */
2063                 if (!net_spoolss_open_printer_ex(pipe_hnd_dst, mem_ctx, sharename,
2064                         PRINTER_ALL_ACCESS, cli->user_name, &hnd_dst)) {
2065
2066                         DEBUG(1,("could not open printer: %s\n", sharename));
2067                 }
2068
2069                 /* check for existing dst printer */
2070                 if (!net_spoolss_getprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, level, &info_dst)) {
2071                         printf (_("could not get printer, creating printer.\n"));
2072                 } else {
2073                         DEBUG(1,("printer already exists: %s\n", sharename));
2074                         /* close printer handle here - dst only, not got src yet. */
2075                         if (is_valid_policy_hnd(&hnd_dst)) {
2076                                 rpccli_spoolss_ClosePrinter(pipe_hnd_dst, mem_ctx, &hnd_dst, NULL);
2077                         }
2078                         continue;
2079                 }
2080
2081                 /* now get again src printer ctr via getprinter,
2082                    we first need a handle for that */
2083
2084                 /* open src printer handle */
2085                 if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, sharename,
2086                         MAXIMUM_ALLOWED_ACCESS, cli->user_name, &hnd_src))
2087                         goto done;
2088
2089                 /* getprinter on the src server */
2090                 if (!net_spoolss_getprinter(pipe_hnd, mem_ctx, &hnd_src, level, &info_src))
2091                         goto done;
2092
2093                 /* copy each src printer to a dst printer 1:1,
2094                    maybe some values have to be changed though */
2095                 d_printf(_("creating printer: %s\n"), printername);
2096
2097                 info_ctr.level = level;
2098                 info_ctr.info.info2 = (struct spoolss_SetPrinterInfo2 *)
2099                         (void *)&info_src.info2;
2100
2101                 result = rpccli_spoolss_addprinterex(pipe_hnd_dst,
2102                                                      mem_ctx,
2103                                                      &info_ctr);
2104
2105                 if (W_ERROR_IS_OK(result))
2106                         d_printf (_("printer [%s] successfully added.\n"),
2107                                   printername);
2108                 else if (W_ERROR_V(result) == W_ERROR_V(WERR_PRINTER_ALREADY_EXISTS))
2109                         d_fprintf (stderr, _("printer [%s] already exists.\n"),
2110                                    printername);
2111                 else {
2112                         d_fprintf (stderr, _("could not create printer [%s]\n"),
2113                                    printername);
2114                         goto done;
2115                 }
2116
2117                 /* close printer handles here */
2118                 if (is_valid_policy_hnd(&hnd_src)) {
2119                         rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd_src, NULL);
2120                 }
2121
2122                 if (is_valid_policy_hnd(&hnd_dst)) {
2123                         rpccli_spoolss_ClosePrinter(pipe_hnd_dst, mem_ctx, &hnd_dst, NULL);
2124                 }
2125         }
2126
2127         nt_status = NT_STATUS_OK;
2128
2129 done:
2130         if (is_valid_policy_hnd(&hnd_src))
2131                 rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd_src, NULL);
2132
2133         if (is_valid_policy_hnd(&hnd_dst))
2134                 rpccli_spoolss_ClosePrinter(pipe_hnd_dst, mem_ctx, &hnd_dst, NULL);
2135
2136         if (cli_dst) {
2137                 cli_shutdown(cli_dst);
2138         }
2139         return nt_status;
2140 }
2141
2142 /**
2143  * Migrate Printer-Settings from a src server to the dst server
2144  * (for this to work, printers and drivers already have to be migrated earlier)
2145  *
2146  * All parameters are provided by the run_rpc_command function, except for
2147  * argc, argv which are passed through.
2148  *
2149  * @param c     A net_context structure
2150  * @param domain_sid The domain sid aquired from the remote server
2151  * @param cli A cli_state connected to the server.
2152  * @param mem_ctx Talloc context, destoyed on compleation of the function.
2153  * @param argc  Standard main() style argc
2154  * @param argv  Standard main() style argv.  Initial components are already
2155  *              stripped
2156  *
2157  * @return Normal NTSTATUS return.
2158  **/
2159
2160 NTSTATUS rpc_printer_migrate_settings_internals(struct net_context *c,
2161                                                 const DOM_SID *domain_sid,
2162                                                 const char *domain_name,
2163                                                 struct cli_state *cli,
2164                                                 struct rpc_pipe_client *pipe_hnd,
2165                                                 TALLOC_CTX *mem_ctx,
2166                                                 int argc,
2167                                                 const char **argv)
2168 {
2169
2170         /* FIXME: Here the nightmare begins */
2171
2172         WERROR result;
2173         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
2174         uint32_t i = 0, p = 0, j = 0;
2175         uint32_t num_printers;
2176         uint32_t level = 2;
2177         const char *printername, *sharename;
2178         struct rpc_pipe_client *pipe_hnd_dst = NULL;
2179         struct policy_handle hnd_src, hnd_dst;
2180         union spoolss_PrinterInfo *info_enum;
2181         union spoolss_PrinterInfo info_dst_publish;
2182         union spoolss_PrinterInfo info_dst;
2183         struct cli_state *cli_dst = NULL;
2184         char *devicename = NULL, *unc_name = NULL, *url = NULL;
2185         const char *longname;
2186         const char **keylist = NULL;
2187
2188         /* FIXME GD */
2189         ZERO_STRUCT(info_dst_publish);
2190
2191         DEBUG(3,("copying printer settings\n"));
2192
2193         /* connect destination PI_SPOOLSS */
2194         nt_status = connect_dst_pipe(c, &cli_dst, &pipe_hnd_dst,
2195                                      &ndr_table_spoolss.syntax_id);
2196         if (!NT_STATUS_IS_OK(nt_status))
2197                 return nt_status;
2198
2199         /* enum src printers */
2200         if (!get_printer_info(pipe_hnd, mem_ctx, level, argc, argv, &num_printers, &info_enum)) {
2201                 nt_status = NT_STATUS_UNSUCCESSFUL;
2202                 goto done;
2203         }
2204
2205         if (!num_printers) {
2206                 printf (_("no printers found on server.\n"));
2207                 nt_status = NT_STATUS_OK;
2208                 goto done;
2209         }
2210
2211
2212         /* needed for dns-strings in regkeys */
2213         longname = get_mydnsfullname();
2214         if (!longname) {
2215                 nt_status = NT_STATUS_UNSUCCESSFUL;
2216                 goto done;
2217         }
2218
2219         /* do something for all printers */
2220         for (i = 0; i < num_printers; i++) {
2221
2222                 uint32_t value_offered = 0, value_needed;
2223                 uint32_t data_offered = 0, data_needed;
2224                 enum winreg_Type type;
2225                 uint8_t *buffer = NULL;
2226                 const char *value_name = NULL;
2227
2228                 /* do some initialization */
2229                 printername = info_enum[i].info2.printername;
2230                 sharename = info_enum[i].info2.sharename;
2231
2232                 if (!printername || !sharename) {
2233                         nt_status = NT_STATUS_UNSUCCESSFUL;
2234                         goto done;
2235                 }
2236                 /* we can reset NT_STATUS here because we do not
2237                    get any real NT_STATUS-codes anymore from now on */
2238                 nt_status = NT_STATUS_UNSUCCESSFUL;
2239
2240                 d_printf(_("migrating printer settings for: [%s] / [%s]\n"),
2241                         printername, sharename);
2242
2243
2244                 /* open src printer handle */
2245                 if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, sharename,
2246                         MAXIMUM_ALLOWED_ACCESS, cli->user_name, &hnd_src))
2247                         goto done;
2248
2249                 /* open dst printer handle */
2250                 if (!net_spoolss_open_printer_ex(pipe_hnd_dst, mem_ctx, sharename,
2251                         PRINTER_ALL_ACCESS, cli_dst->user_name, &hnd_dst))
2252                         goto done;
2253
2254                 /* check for existing dst printer */
2255                 if (!net_spoolss_getprinter(pipe_hnd_dst, mem_ctx, &hnd_dst,
2256                                 level, &info_dst))
2257                         goto done;
2258
2259
2260                 /* STEP 1: COPY DEVICE-MODE and other
2261                            PRINTER_INFO_2-attributes
2262                 */
2263
2264                 info_dst.info2 = info_enum[i].info2;
2265
2266                 /* why is the port always disconnected when the printer
2267                    is correctly installed (incl. driver ???) */
2268                 info_dst.info2.portname = SAMBA_PRINTER_PORT_NAME;
2269
2270                 /* check if printer is published */
2271                 if (info_enum[i].info2.attributes & PRINTER_ATTRIBUTE_PUBLISHED) {
2272
2273                         /* check for existing dst printer */
2274                         if (!net_spoolss_getprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, 7, &info_dst_publish))
2275                                 goto done;
2276
2277                         info_dst_publish.info7.action = DSPRINT_PUBLISH;
2278
2279                         /* ignore false from setprinter due to WERR_IO_PENDING */
2280                         net_spoolss_setprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, 7, &info_dst_publish);
2281
2282                         DEBUG(3,("republished printer\n"));
2283                 }
2284
2285                 if (info_enum[i].info2.devmode != NULL) {
2286
2287                         /* copy devmode (info level 2) */
2288                         info_dst.info2.devmode = info_enum[i].info2.devmode;
2289
2290                         /* do not copy security descriptor (we have another
2291                          * command for that) */
2292                         info_dst.info2.secdesc = NULL;
2293
2294 #if 0
2295                         info_dst.info2.devmode.devicename =
2296                                 talloc_asprintf(mem_ctx, "\\\\%s\\%s",
2297                                                 longname, printername);
2298                         if (!info_dst.info2.devmode.devicename) {
2299                                 nt_status = NT_STATUS_NO_MEMORY;
2300                                 goto done;
2301                         }
2302 #endif
2303                         if (!net_spoolss_setprinter(pipe_hnd_dst, mem_ctx, &hnd_dst,
2304                                                     level, &info_dst))
2305                                 goto done;
2306
2307                         DEBUGADD(1,("\tSetPrinter of DEVICEMODE succeeded\n"));
2308                 }
2309
2310                 /* STEP 2: COPY REGISTRY VALUES */
2311
2312                 /* please keep in mind that samba parse_spools gives horribly
2313                    crippled results when used to rpccli_spoolss_enumprinterdataex
2314                    a win2k3-server.  (Bugzilla #1851)
2315                    FIXME: IIRC I've seen it too on a win2k-server
2316                 */
2317
2318                 /* enumerate data on src handle */
2319                 nt_status = rpccli_spoolss_EnumPrinterData(pipe_hnd, mem_ctx,
2320                                                            &hnd_src,
2321                                                            p,
2322                                                            value_name,
2323                                                            value_offered,
2324                                                            &value_needed,
2325                                                            &type,
2326                                                            buffer,
2327                                                            data_offered,
2328                                                            &data_needed,
2329                                                            &result);
2330
2331                 data_offered    = data_needed;
2332                 value_offered   = value_needed;
2333                 buffer          = talloc_zero_array(mem_ctx, uint8_t, data_needed);
2334                 value_name      = talloc_zero_array(mem_ctx, char, value_needed);
2335
2336                 /* loop for all printerdata of "PrinterDriverData" */
2337                 while (NT_STATUS_IS_OK(nt_status) && W_ERROR_IS_OK(result)) {
2338
2339                         nt_status = rpccli_spoolss_EnumPrinterData(pipe_hnd, mem_ctx,
2340                                                                    &hnd_src,
2341                                                                    p++,
2342                                                                    value_name,
2343                                                                    value_offered,
2344                                                                    &value_needed,
2345                                                                    &type,
2346                                                                    buffer,
2347                                                                    data_offered,
2348                                                                    &data_needed,
2349                                                                    &result);
2350                         /* loop for all reg_keys */
2351                         if (NT_STATUS_IS_OK(nt_status) && W_ERROR_IS_OK(result)) {
2352
2353                                 struct regval_blob v;
2354                                 DATA_BLOB blob;
2355                                 union spoolss_PrinterData printer_data;
2356
2357                                 /* display_value */
2358                                 if (c->opt_verbose) {
2359                                         fstrcpy(v.valuename, value_name);
2360                                         v.type = type;
2361                                         v.size = data_offered;
2362                                         v.data_p = buffer;
2363                                         display_reg_value(SPOOL_PRINTERDATA_KEY, v);
2364                                 }
2365
2366                                 result = pull_spoolss_PrinterData(mem_ctx,
2367                                                                   &blob,
2368                                                                   &printer_data,
2369                                                                   type);
2370                                 if (!W_ERROR_IS_OK(result)) {
2371                                         goto done;
2372                                 }
2373
2374                                 /* set_value */
2375                                 if (!net_spoolss_setprinterdata(pipe_hnd_dst, mem_ctx,
2376                                                                 &hnd_dst, value_name,
2377                                                                 type, printer_data))
2378                                         goto done;
2379
2380                                 DEBUGADD(1,("\tSetPrinterData of [%s] succeeded\n",
2381                                         v.valuename));
2382                         }
2383                 }
2384
2385                 /* STEP 3: COPY SUBKEY VALUES */
2386
2387                 /* here we need to enum all printer_keys and then work
2388                    on the result with enum_printer_key_ex. nt4 does not
2389                    respond to enumprinterkey, win2k does, so continue
2390                    in case of an error */
2391
2392                 if (!net_spoolss_enumprinterkey(pipe_hnd, mem_ctx, &hnd_src, "", &keylist)) {
2393                         printf(_("got no key-data\n"));
2394                         continue;
2395                 }
2396
2397
2398                 /* work on a list of printer keys
2399                    each key has to be enumerated to get all required
2400                    information.  information is then set via setprinterdataex-calls */
2401
2402                 if (keylist == NULL)
2403                         continue;
2404
2405                 for (i=0; keylist && keylist[i] != NULL; i++) {
2406
2407                         const char *subkey = keylist[i];
2408                         uint32_t count;
2409                         struct spoolss_PrinterEnumValues *info;
2410
2411                         /* enumerate all src subkeys */
2412                         if (!net_spoolss_enumprinterdataex(pipe_hnd, mem_ctx, 0,
2413                                                            &hnd_src, subkey,
2414                                                            &count, &info)) {
2415                                 goto done;
2416                         }
2417
2418                         for (j=0; j < count; j++) {
2419
2420                                 struct regval_blob value;
2421                                 DATA_BLOB blob;
2422
2423                                 /* although samba replies with sane data in most cases we
2424                                    should try to avoid writing wrong registry data */
2425
2426                                 if (strequal(info[j].value_name, SPOOL_REG_PORTNAME) ||
2427                                     strequal(info[j].value_name, SPOOL_REG_UNCNAME) ||
2428                                     strequal(info[j].value_name, SPOOL_REG_URL) ||
2429                                     strequal(info[j].value_name, SPOOL_REG_SHORTSERVERNAME) ||
2430                                     strequal(info[j].value_name, SPOOL_REG_SERVERNAME)) {
2431
2432                                         if (strequal(info[j].value_name, SPOOL_REG_PORTNAME)) {
2433
2434                                                 /* although windows uses a multi-sz, we use a sz */
2435                                                 push_reg_sz(mem_ctx, &blob, SAMBA_PRINTER_PORT_NAME);
2436                                                 fstrcpy(value.valuename, SPOOL_REG_PORTNAME);
2437                                         }
2438
2439                                         if (strequal(info[j].value_name, SPOOL_REG_UNCNAME)) {
2440
2441                                                 if (asprintf(&unc_name, "\\\\%s\\%s", longname, sharename) < 0) {
2442                                                         nt_status = NT_STATUS_NO_MEMORY;
2443                                                         goto done;
2444                                                 }
2445                                                 push_reg_sz(mem_ctx, &blob, unc_name);
2446                                                 fstrcpy(value.valuename, SPOOL_REG_UNCNAME);
2447                                         }
2448
2449                                         if (strequal(info[j].value_name, SPOOL_REG_URL)) {
2450
2451                                                 continue;
2452
2453 #if 0
2454                                                 /* FIXME: should we really do that ??? */
2455                                                 if (asprintf(&url, "http://%s:631/printers/%s", longname, sharename) < 0) {
2456                                                         nt_status = NT_STATUS_NO_MEMORY;
2457                                                         goto done;
2458                                                 }
2459                                                 push_reg_sz(mem_ctx, &blob, url);
2460                                                 fstrcpy(value.valuename, SPOOL_REG_URL);
2461 #endif
2462                                         }
2463
2464                                         if (strequal(info[j].value_name, SPOOL_REG_SERVERNAME)) {
2465
2466                                                 push_reg_sz(mem_ctx, &blob, longname);
2467                                                 fstrcpy(value.valuename, SPOOL_REG_SERVERNAME);
2468                                         }
2469
2470                                         if (strequal(info[j].value_name, SPOOL_REG_SHORTSERVERNAME)) {
2471
2472                                                 push_reg_sz(mem_ctx, &blob, global_myname());
2473                                                 fstrcpy(value.valuename, SPOOL_REG_SHORTSERVERNAME);
2474                                         }
2475
2476                                         value.type = REG_SZ;
2477                                         value.size = blob.length;
2478                                         if (value.size) {
2479                                                 value.data_p = blob.data;
2480                                         } else {
2481                                                 value.data_p = NULL;
2482                                         }
2483
2484                                         if (c->opt_verbose)
2485                                                 display_reg_value(subkey, value);
2486
2487                                         /* here we have to set all subkeys on the dst server */
2488                                         if (!net_spoolss_setprinterdataex(pipe_hnd_dst, mem_ctx, &hnd_dst,
2489                                                         subkey, &value))
2490                                                 goto done;
2491
2492                                 } else {
2493
2494                                         struct regval_blob v;
2495
2496                                         result = push_spoolss_PrinterData(mem_ctx, &blob,
2497                                                                           info[j].type,
2498                                                                           info[j].data);
2499                                         if (!W_ERROR_IS_OK(result)) {
2500                                                 goto done;
2501                                         }
2502
2503                                         fstrcpy(v.valuename, info[j].value_name);
2504                                         v.type = info[j].type;
2505                                         v.data_p = blob.data;
2506                                         v.size = blob.length;
2507
2508                                         if (c->opt_verbose) {
2509                                                 display_reg_value(subkey, v);
2510                                         }
2511
2512                                         /* here we have to set all subkeys on the dst server */
2513                                         if (!net_spoolss_setprinterdataex(pipe_hnd_dst, mem_ctx, &hnd_dst,
2514                                                         subkey, &v)) {
2515                                                 goto done;
2516                                         }
2517
2518                                 }
2519
2520                                 DEBUGADD(1,("\tSetPrinterDataEx of key [%s\\%s] succeeded\n",
2521                                                 subkey, info[j].value_name));
2522
2523                         }
2524                 }
2525
2526                 TALLOC_FREE(keylist);
2527
2528                 /* close printer handles here */
2529                 if (is_valid_policy_hnd(&hnd_src)) {
2530                         rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd_src, NULL);
2531                 }
2532
2533                 if (is_valid_policy_hnd(&hnd_dst)) {
2534                         rpccli_spoolss_ClosePrinter(pipe_hnd_dst, mem_ctx, &hnd_dst, NULL);
2535                 }
2536
2537         }
2538
2539         nt_status = NT_STATUS_OK;
2540
2541 done:
2542         SAFE_FREE(devicename);
2543         SAFE_FREE(url);
2544         SAFE_FREE(unc_name);
2545
2546         if (is_valid_policy_hnd(&hnd_src))
2547                 rpccli_spoolss_ClosePrinter(pipe_hnd, mem_ctx, &hnd_src, NULL);
2548
2549         if (is_valid_policy_hnd(&hnd_dst))
2550                 rpccli_spoolss_ClosePrinter(pipe_hnd_dst, mem_ctx, &hnd_dst, NULL);
2551
2552         if (cli_dst) {
2553                 cli_shutdown(cli_dst);
2554         }
2555         return nt_status;
2556 }