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