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