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