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