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