utils/net_rpc_printer.c

説明を見る。
00001 /* 
00002    Samba Unix/Linux SMB client library 
00003    Distributed SMB/CIFS Server Management Utility 
00004    Copyright (C) 2004 Guenther Deschner (gd@samba.org)
00005 
00006    This program is free software; you can redistribute it and/or modify
00007    it under the terms of the GNU General Public License as published by
00008    the Free Software Foundation; either version 2 of the License, or
00009    (at your option) any later version.
00010    
00011    This program is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014    GNU General Public License for more details.
00015    
00016    You should have received a copy of the GNU General Public License
00017    along with this program; if not, write to the Free Software
00018    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
00019  
00020 #include "includes.h"
00021 #include "utils/net.h"
00022 
00023 struct table_node {
00024         const char *long_archi;
00025         const char *short_archi;
00026         int version;
00027 };
00028 
00029 
00030 /* support itanium as well */
00031 static const struct table_node archi_table[]= {
00032 
00033         {"Windows 4.0",          "WIN40",       0 },
00034         {"Windows NT x86",       "W32X86",      2 },
00035         {"Windows NT x86",       "W32X86",      3 },
00036         {"Windows NT R4000",     "W32MIPS",     2 },
00037         {"Windows NT Alpha_AXP", "W32ALPHA",    2 },
00038         {"Windows NT PowerPC",   "W32PPC",      2 },
00039         {"Windows IA64",         "IA64",        3 },
00040         {"Windows x64",          "x64",         3 },
00041         {NULL,                   "",            -1 }
00042 };
00043 
00044 
00045 /**
00046  * This display-printdriver-functions was borrowed from rpcclient/cmd_spoolss.c.
00047  * It is here for debugging purpose and should be removed later on.
00048  **/
00049 
00050 /****************************************************************************
00051  Printer info level 3 display function.
00052 ****************************************************************************/
00053 
00054 static void display_print_driver_3(DRIVER_INFO_3 *i1)
00055 {
00056         fstring name = "";
00057         fstring architecture = "";
00058         fstring driverpath = "";
00059         fstring datafile = "";
00060         fstring configfile = "";
00061         fstring helpfile = "";
00062         fstring dependentfiles = "";
00063         fstring monitorname = "";
00064         fstring defaultdatatype = "";
00065         
00066         int length=0;
00067         BOOL valid = True;
00068         
00069         if (i1 == NULL)
00070                 return;
00071 
00072         rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
00073         rpcstr_pull(architecture, i1->architecture.buffer, sizeof(architecture), -1, STR_TERMINATE);
00074         rpcstr_pull(driverpath, i1->driverpath.buffer, sizeof(driverpath), -1, STR_TERMINATE);
00075         rpcstr_pull(datafile, i1->datafile.buffer, sizeof(datafile), -1, STR_TERMINATE);
00076         rpcstr_pull(configfile, i1->configfile.buffer, sizeof(configfile), -1, STR_TERMINATE);
00077         rpcstr_pull(helpfile, i1->helpfile.buffer, sizeof(helpfile), -1, STR_TERMINATE);
00078         rpcstr_pull(monitorname, i1->monitorname.buffer, sizeof(monitorname), -1, STR_TERMINATE);
00079         rpcstr_pull(defaultdatatype, i1->defaultdatatype.buffer, sizeof(defaultdatatype), -1, STR_TERMINATE);
00080 
00081         d_printf ("Printer Driver Info 3:\n");
00082         d_printf ("\tVersion: [%x]\n", i1->version);
00083         d_printf ("\tDriver Name: [%s]\n",name);
00084         d_printf ("\tArchitecture: [%s]\n", architecture);
00085         d_printf ("\tDriver Path: [%s]\n", driverpath);
00086         d_printf ("\tDatafile: [%s]\n", datafile);
00087         d_printf ("\tConfigfile: [%s]\n", configfile);
00088         d_printf ("\tHelpfile: [%s]\n\n", helpfile);
00089 
00090         while (valid) {
00091                 rpcstr_pull(dependentfiles, i1->dependentfiles+length, sizeof(dependentfiles), -1, STR_TERMINATE);
00092                 
00093                 length+=strlen(dependentfiles)+1;
00094                 
00095                 if (strlen(dependentfiles) > 0) {
00096                         d_printf ("\tDependentfiles: [%s]\n", dependentfiles);
00097                 } else {
00098                         valid = False;
00099                 }
00100         }
00101         
00102         printf ("\n");
00103 
00104         d_printf ("\tMonitorname: [%s]\n", monitorname);
00105         d_printf ("\tDefaultdatatype: [%s]\n\n", defaultdatatype);
00106 
00107         return; 
00108 }
00109 
00110 static void display_reg_value(const char *subkey, REGISTRY_VALUE value)
00111 {
00112         pstring text;
00113 
00114         switch(value.type) {
00115         case REG_DWORD:
00116                 d_printf("\t[%s:%s]: REG_DWORD: 0x%08x\n", subkey, value.valuename, 
00117                        *((uint32 *) value.data_p));
00118                 break;
00119 
00120         case REG_SZ:
00121                 rpcstr_pull(text, value.data_p, sizeof(text), value.size,
00122                             STR_TERMINATE);
00123                 d_printf("\t[%s:%s]: REG_SZ: %s\n", subkey, value.valuename, text);
00124                 break;
00125 
00126         case REG_BINARY: 
00127                 d_printf("\t[%s:%s]: REG_BINARY: unknown length value not displayed\n", 
00128                          subkey, value.valuename);
00129                 break;
00130 
00131         case REG_MULTI_SZ: {
00132                 uint16 *curstr = (uint16 *) value.data_p;
00133                 uint8 *start = value.data_p;
00134                 d_printf("\t[%s:%s]: REG_MULTI_SZ:\n", subkey, value.valuename);
00135                 while ((*curstr != 0) && 
00136                        ((uint8 *) curstr < start + value.size)) {
00137                         rpcstr_pull(text, curstr, sizeof(text), -1, 
00138                                     STR_TERMINATE);
00139                         d_printf("%s\n", text);
00140                         curstr += strlen(text) + 1;
00141                 }
00142         }
00143         break;
00144 
00145         default:
00146                 d_printf("\t%s: unknown type %d\n", value.valuename, value.type);
00147         }
00148         
00149 }
00150 
00151 /**
00152  * Copies ACLs, DOS-attributes and timestamps from one 
00153  * file or directory from one connected share to another connected share 
00154  *
00155  * @param mem_ctx               A talloc-context
00156  * @param cli_share_src         A connected cli_state 
00157  * @param cli_share_dst         A connected cli_state 
00158  * @param src_file              The source file-name
00159  * @param dst_file              The destination file-name
00160  * @param copy_acls             Whether to copy acls
00161  * @param copy_attrs            Whether to copy DOS attributes
00162  * @param copy_timestamps       Whether to preserve timestamps
00163  * @param is_file               Whether this file is a file or a dir
00164  *
00165  * @return Normal NTSTATUS return.
00166  **/ 
00167 
00168 NTSTATUS net_copy_fileattr(TALLOC_CTX *mem_ctx,
00169                   struct cli_state *cli_share_src,
00170                   struct cli_state *cli_share_dst, 
00171                   const char *src_name, const char *dst_name,
00172                   BOOL copy_acls, BOOL copy_attrs,
00173                   BOOL copy_timestamps, BOOL is_file)
00174 {
00175         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
00176         int fnum_src = 0;
00177         int fnum_dst = 0;
00178         SEC_DESC *sd = NULL;
00179         uint16 attr;
00180         time_t f_atime, f_ctime, f_mtime;
00181 
00182 
00183         if (!copy_timestamps && !copy_acls && !copy_attrs)
00184                 return NT_STATUS_OK;
00185 
00186         /* open file/dir on the originating server */
00187 
00188         DEBUGADD(3,("opening %s %s on originating server\n", 
00189                 is_file?"file":"dir", src_name));
00190 
00191         fnum_src = cli_nt_create(cli_share_src, src_name, READ_CONTROL_ACCESS);
00192         if (fnum_src == -1) {
00193                 DEBUGADD(0,("cannot open %s %s on originating server %s\n", 
00194                         is_file?"file":"dir", src_name, cli_errstr(cli_share_src)));
00195                 nt_status = cli_nt_error(cli_share_src);
00196                 goto out;
00197         }
00198 
00199 
00200         if (copy_acls) {
00201 
00202                 /* get the security descriptor */
00203                 sd = cli_query_secdesc(cli_share_src, fnum_src, mem_ctx);
00204                 if (!sd) {
00205                         DEBUG(0,("failed to get security descriptor: %s\n",
00206                                 cli_errstr(cli_share_src)));
00207                         nt_status = cli_nt_error(cli_share_src);
00208                         goto out;
00209                 }
00210 
00211                 if (opt_verbose && DEBUGLEVEL >= 3)
00212                         display_sec_desc(sd);
00213         }
00214 
00215 
00216         if (copy_attrs || copy_timestamps) {
00217 
00218                 /* get file attributes */
00219                 if (!cli_getattrE(cli_share_src, fnum_src, &attr, NULL, 
00220                                  &f_ctime, &f_atime, &f_mtime)) {
00221                         DEBUG(0,("failed to get file-attrs: %s\n", 
00222                                 cli_errstr(cli_share_src)));
00223                         nt_status = cli_nt_error(cli_share_src);
00224                         goto out;
00225                 }
00226         }
00227 
00228 
00229         /* open the file/dir on the destination server */ 
00230 
00231         fnum_dst = cli_nt_create(cli_share_dst, dst_name, WRITE_DAC_ACCESS | WRITE_OWNER_ACCESS);
00232         if (fnum_dst == -1) {
00233                 DEBUG(0,("failed to open %s on the destination server: %s: %s\n",
00234                         is_file?"file":"dir", dst_name, cli_errstr(cli_share_dst)));
00235                 nt_status = cli_nt_error(cli_share_dst);
00236                 goto out;
00237         }
00238 
00239         if (copy_timestamps) {
00240 
00241                 /* set timestamps */
00242                 if (!cli_setattrE(cli_share_dst, fnum_dst, f_ctime, f_atime, f_mtime)) {
00243                         DEBUG(0,("failed to set file-attrs (timestamps): %s\n",
00244                                 cli_errstr(cli_share_dst)));
00245                         nt_status = cli_nt_error(cli_share_dst);
00246                         goto out;
00247                 }
00248         }
00249 
00250         if (copy_acls) {
00251 
00252                 /* set acls */
00253                 if (!cli_set_secdesc(cli_share_dst, fnum_dst, sd)) {
00254                         DEBUG(0,("could not set secdesc on %s: %s\n",
00255                                 dst_name, cli_errstr(cli_share_dst)));
00256                         nt_status = cli_nt_error(cli_share_dst);
00257                         goto out;
00258                 }
00259         }
00260 
00261         if (copy_attrs) {
00262 
00263                 /* set attrs */
00264                 if (!cli_setatr(cli_share_dst, dst_name, attr, 0)) {
00265                         DEBUG(0,("failed to set file-attrs: %s\n",
00266                                 cli_errstr(cli_share_dst)));
00267                         nt_status = cli_nt_error(cli_share_dst);
00268                         goto out;
00269                 }
00270         }
00271 
00272 
00273         /* closing files */
00274 
00275         if (!cli_close(cli_share_src, fnum_src)) {
00276                 d_fprintf(stderr, "could not close %s on originating server: %s\n", 
00277                         is_file?"file":"dir", cli_errstr(cli_share_src));
00278                 nt_status = cli_nt_error(cli_share_src);
00279                 goto out;
00280         }
00281 
00282         if (!cli_close(cli_share_dst, fnum_dst)) {
00283                 d_fprintf(stderr, "could not close %s on destination server: %s\n", 
00284                         is_file?"file":"dir", cli_errstr(cli_share_dst));
00285                 nt_status = cli_nt_error(cli_share_dst);
00286                 goto out;
00287         }
00288 
00289 
00290         nt_status = NT_STATUS_OK;
00291 
00292 out:
00293 
00294         /* cleaning up */
00295         if (fnum_src)
00296                 cli_close(cli_share_src, fnum_src);
00297 
00298         if (fnum_dst)
00299                 cli_close(cli_share_dst, fnum_dst);
00300 
00301         return nt_status;
00302 }
00303 
00304 /**
00305  * Copy a file or directory from a connected share to another connected share 
00306  *
00307  * @param mem_ctx               A talloc-context
00308  * @param cli_share_src         A connected cli_state 
00309  * @param cli_share_dst         A connected cli_state 
00310  * @param src_file              The source file-name
00311  * @param dst_file              The destination file-name
00312  * @param copy_acls             Whether to copy acls
00313  * @param copy_attrs            Whether to copy DOS attributes
00314  * @param copy_timestamps       Whether to preserve timestamps
00315  * @param is_file               Whether this file is a file or a dir
00316  *
00317  * @return Normal NTSTATUS return.
00318  **/ 
00319 
00320 NTSTATUS net_copy_file(TALLOC_CTX *mem_ctx,
00321                        struct cli_state *cli_share_src,
00322                        struct cli_state *cli_share_dst, 
00323                        const char *src_name, const char *dst_name,
00324                        BOOL copy_acls, BOOL copy_attrs,
00325                        BOOL copy_timestamps, BOOL is_file)
00326 {
00327         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
00328         int fnum_src = 0;
00329         int fnum_dst = 0;
00330         static int io_bufsize = 64512;
00331         int read_size = io_bufsize;
00332         char *data = NULL;
00333         off_t start = 0;
00334         off_t nread = 0;
00335 
00336 
00337         if (!src_name || !dst_name)
00338                 goto out;
00339 
00340         if (cli_share_src == NULL || cli_share_dst == NULL)
00341                 goto out; 
00342                 
00343 
00344         /* open on the originating server */
00345         DEBUGADD(3,("opening %s %s on originating server\n", 
00346                 is_file ? "file":"dir", src_name));
00347         if (is_file)
00348                 fnum_src = cli_open(cli_share_src, src_name, O_RDONLY, DENY_NONE);
00349         else
00350                 fnum_src = cli_nt_create(cli_share_src, src_name, READ_CONTROL_ACCESS);
00351 
00352         if (fnum_src == -1) {
00353                 DEBUGADD(0,("cannot open %s %s on originating server %s\n",
00354                         is_file ? "file":"dir",
00355                         src_name, cli_errstr(cli_share_src)));
00356                 nt_status = cli_nt_error(cli_share_src);
00357                 goto out;
00358         }
00359 
00360 
00361         if (is_file) {
00362 
00363                 /* open file on the destination server */
00364                 DEBUGADD(3,("opening file %s on destination server\n", dst_name));
00365                 fnum_dst = cli_open(cli_share_dst, dst_name, 
00366                                 O_RDWR|O_CREAT|O_TRUNC, DENY_NONE);
00367 
00368                 if (fnum_dst == -1) {
00369                         DEBUGADD(1,("cannot create file %s on destination server: %s\n", 
00370                                 dst_name, cli_errstr(cli_share_dst)));
00371                         nt_status = cli_nt_error(cli_share_dst);
00372                         goto out;
00373                 }
00374 
00375                 /* allocate memory */
00376                 if (!(data = (char *)SMB_MALLOC(read_size))) {
00377                         d_fprintf(stderr, "malloc fail for size %d\n", read_size);
00378                         nt_status = NT_STATUS_NO_MEMORY;
00379                         goto out;
00380                 }
00381 
00382         }
00383 
00384 
00385         if (opt_verbose) {
00386 
00387                 d_printf("copying [\\\\%s\\%s%s] => [\\\\%s\\%s%s] "
00388                          "%s ACLs and %s DOS Attributes %s\n", 
00389                         cli_share_src->desthost, cli_share_src->share, src_name,
00390                         cli_share_dst->desthost, cli_share_dst->share, dst_name,
00391                         copy_acls ?  "with" : "without", 
00392                         copy_attrs ? "with" : "without",
00393                         copy_timestamps ? "(preserving timestamps)" : "" );
00394         }
00395 
00396 
00397         while (is_file) {
00398 
00399                 /* copying file */
00400                 int n, ret;
00401                 n = cli_read(cli_share_src, fnum_src, data, nread + start, 
00402                                 read_size);
00403 
00404                 if (n <= 0)
00405                         break;
00406 
00407                 ret = cli_write(cli_share_dst, fnum_dst, 0, data, 
00408                         nread + start, n);
00409 
00410                 if (n != ret) {
00411                         d_fprintf(stderr, "Error writing file: %s\n", 
00412                                 cli_errstr(cli_share_dst));
00413                         nt_status = cli_nt_error(cli_share_dst);
00414                         goto out;
00415                 }
00416 
00417                 nread += n;
00418         }
00419 
00420 
00421         if (!is_file && !cli_chkpath(cli_share_dst, dst_name)) {
00422 
00423                 /* creating dir */
00424                 DEBUGADD(3,("creating dir %s on the destination server\n", 
00425                         dst_name));
00426 
00427                 if (!cli_mkdir(cli_share_dst, dst_name)) {
00428                         DEBUG(0,("cannot create directory %s: %s\n",
00429                                 dst_name, cli_errstr(cli_share_dst)));
00430                         nt_status = NT_STATUS_NO_SUCH_FILE;
00431                 }
00432 
00433                 if (!cli_chkpath(cli_share_dst, dst_name)) {
00434                         d_fprintf(stderr, "cannot check for directory %s: %s\n",
00435                                 dst_name, cli_errstr(cli_share_dst));
00436                         goto out;
00437                 }
00438         }
00439 
00440 
00441         /* closing files */
00442         if (!cli_close(cli_share_src, fnum_src)) {
00443                 d_fprintf(stderr, "could not close file on originating server: %s\n", 
00444                         cli_errstr(cli_share_src));
00445                 nt_status = cli_nt_error(cli_share_src);
00446                 goto out;
00447         }
00448 
00449         if (is_file && !cli_close(cli_share_dst, fnum_dst)) {
00450                 d_fprintf(stderr, "could not close file on destination server: %s\n", 
00451                         cli_errstr(cli_share_dst));
00452                 nt_status = cli_nt_error(cli_share_dst);
00453                 goto out;
00454         }
00455 
00456         /* possibly we have to copy some file-attributes / acls / sd */
00457         nt_status = net_copy_fileattr(mem_ctx, cli_share_src, cli_share_dst, 
00458                                       src_name, dst_name, copy_acls, 
00459                                       copy_attrs, copy_timestamps, is_file);
00460         if (!NT_STATUS_IS_OK(nt_status))
00461                 goto out;
00462 
00463 
00464         nt_status = NT_STATUS_OK;
00465 
00466 out:
00467 
00468         /* cleaning up */
00469         if (fnum_src)
00470                 cli_close(cli_share_src, fnum_src);
00471 
00472         if (fnum_dst)
00473                 cli_close(cli_share_dst, fnum_dst);
00474 
00475         SAFE_FREE(data);
00476 
00477         return nt_status;
00478 }
00479 
00480 /**
00481  * Copy a driverfile from on connected share to another connected share 
00482  * This silently assumes that a driver-file is picked up from 
00483  *
00484  *      \\src_server\print$\{arch}\{version}\file 
00485  *
00486  * and copied to
00487  *
00488  *      \\dst_server\print$\{arch}\file 
00489  * 
00490  * to be added via setdriver-calls later.
00491  * @param mem_ctx               A talloc-context
00492  * @param cli_share_src         A cli_state connected to source print$-share
00493  * @param cli_share_dst         A cli_state connected to destination print$-share
00494  * @param file                  The file-name to be copied 
00495  * @param short_archi           The name of the driver-architecture (short form)
00496  *
00497  * @return Normal NTSTATUS return.
00498  **/ 
00499 
00500 static NTSTATUS net_copy_driverfile(TALLOC_CTX *mem_ctx,
00501                                     struct cli_state *cli_share_src,
00502                                     struct cli_state *cli_share_dst, 
00503                                     char *file, const char *short_archi) {
00504 
00505         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
00506         const char *p;
00507         char *src_name;
00508         char *dst_name;
00509         fstring version;
00510         fstring filename;
00511         fstring tok;
00512 
00513         /* scroll through the file until we have the part 
00514            beyond archi_table.short_archi */
00515         p = file;
00516         while (next_token(&p, tok, "\\", sizeof(tok))) {
00517                 if (strequal(tok, short_archi)) {
00518                         next_token(&p, version, "\\", sizeof(version));
00519                         next_token(&p, filename, "\\", sizeof(filename));
00520                 }
00521         }
00522 
00523         /* build source file name */
00524         if (asprintf(&src_name, "\\%s\\%s\\%s", short_archi, version, filename) < 0 ) 
00525                 return NT_STATUS_NO_MEMORY;
00526 
00527 
00528         /* create destination file name */
00529         if (asprintf(&dst_name, "\\%s\\%s", short_archi, filename) < 0 )
00530                 return NT_STATUS_NO_MEMORY;
00531 
00532 
00533         /* finally copy the file */
00534         nt_status = net_copy_file(mem_ctx, cli_share_src, cli_share_dst, 
00535                                   src_name, dst_name, False, False, False, True);
00536         if (!NT_STATUS_IS_OK(nt_status))
00537                 goto out;
00538 
00539         nt_status = NT_STATUS_OK;
00540 
00541 out:
00542         SAFE_FREE(src_name);
00543         SAFE_FREE(dst_name);
00544 
00545         return nt_status;
00546 }
00547 
00548 /**
00549  * Check for existing Architecture directory on a given server
00550  *
00551  * @param cli_share             A cli_state connected to a print$-share
00552  * @param short_archi           The Architecture for the print-driver
00553  *
00554  * @return Normal NTSTATUS return.
00555  **/
00556 
00557 static NTSTATUS check_arch_dir(struct cli_state *cli_share, const char *short_archi)
00558 {
00559 
00560         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
00561         char *dir;
00562 
00563         if (asprintf(&dir, "\\%s", short_archi) < 0) {
00564                 return NT_STATUS_NO_MEMORY;
00565         }
00566 
00567         DEBUG(10,("creating print-driver dir for architecture: %s\n", 
00568                 short_archi));
00569 
00570         if (!cli_mkdir(cli_share, dir)) {
00571                 DEBUG(1,("cannot create directory %s: %s\n",
00572                          dir, cli_errstr(cli_share)));
00573                 nt_status = NT_STATUS_NO_SUCH_FILE;
00574         }
00575 
00576         if (!cli_chkpath(cli_share, dir)) {
00577                 d_fprintf(stderr, "cannot check %s: %s\n", 
00578                         dir, cli_errstr(cli_share));
00579                 goto out;
00580         }
00581 
00582         nt_status = NT_STATUS_OK;
00583 
00584 out:
00585         SAFE_FREE(dir);
00586         return nt_status;
00587 }
00588 
00589 /**
00590  * Copy a print-driver (level 3) from one connected print$-share to another 
00591  * connected print$-share
00592  *
00593  * @param mem_ctx               A talloc-context
00594  * @param cli_share_src         A cli_state connected to a print$-share
00595  * @param cli_share_dst         A cli_state connected to a print$-share
00596  * @param short_archi           The Architecture for the print-driver
00597  * @param i1                    The DRIVER_INFO_3-struct
00598  *
00599  * @return Normal NTSTATUS return.
00600  **/
00601 
00602 static NTSTATUS copy_print_driver_3(TALLOC_CTX *mem_ctx,
00603                     struct cli_state *cli_share_src, 
00604                     struct cli_state *cli_share_dst, 
00605                     const char *short_archi, DRIVER_INFO_3 *i1)
00606 {
00607         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
00608         int length = 0;
00609         BOOL valid = True;
00610         
00611         fstring name = "";
00612         fstring driverpath = "";
00613         fstring datafile = "";
00614         fstring configfile = "";
00615         fstring helpfile = "";
00616         fstring dependentfiles = "";
00617         
00618         if (i1 == NULL)
00619                 return nt_status;
00620 
00621         rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
00622         rpcstr_pull(driverpath, i1->driverpath.buffer, sizeof(driverpath), -1, STR_TERMINATE);
00623         rpcstr_pull(datafile, i1->datafile.buffer, sizeof(datafile), -1, STR_TERMINATE);
00624         rpcstr_pull(configfile, i1->configfile.buffer, sizeof(configfile), -1, STR_TERMINATE);
00625         rpcstr_pull(helpfile, i1->helpfile.buffer, sizeof(helpfile), -1, STR_TERMINATE);
00626 
00627 
00628         if (opt_verbose)
00629                 d_printf("copying driver: [%s], for architecture: [%s], version: [%d]\n", 
00630                           name, short_archi, i1->version);
00631         
00632         nt_status = net_copy_driverfile(mem_ctx, cli_share_src, cli_share_dst, 
00633                 driverpath, short_archi);
00634         if (!NT_STATUS_IS_OK(nt_status))
00635                 return nt_status;
00636                 
00637         nt_status = net_copy_driverfile(mem_ctx, cli_share_src, cli_share_dst, 
00638                 datafile, short_archi);
00639         if (!NT_STATUS_IS_OK(nt_status))
00640                 return nt_status;
00641                 
00642         nt_status = net_copy_driverfile(mem_ctx, cli_share_src, cli_share_dst, 
00643                 configfile, short_archi);
00644         if (!NT_STATUS_IS_OK(nt_status))
00645                 return nt_status;
00646                 
00647         nt_status = net_copy_driverfile(mem_ctx, cli_share_src, cli_share_dst, 
00648                 helpfile, short_archi);
00649         if (!NT_STATUS_IS_OK(nt_status))
00650                 return nt_status;
00651 
00652         while (valid) {
00653                 
00654                 rpcstr_pull(dependentfiles, i1->dependentfiles+length, sizeof(dependentfiles), -1, STR_TERMINATE);
00655                 length += strlen(dependentfiles)+1;
00656                 
00657                 if (strlen(dependentfiles) > 0) {
00658 
00659                         nt_status = net_copy_driverfile(mem_ctx, 
00660                                         cli_share_src, cli_share_dst, 
00661                                         dependentfiles, short_archi);
00662                         if (!NT_STATUS_IS_OK(nt_status))
00663                                 return nt_status;
00664                 } else {
00665                         valid = False;
00666                 }
00667         }
00668 
00669         return NT_STATUS_OK;
00670 }
00671 
00672 /**
00673  * net_spoolss-functions
00674  * =====================
00675  *
00676  * the net_spoolss-functions aim to simplify spoolss-client-functions
00677  * required during the migration-process wrt buffer-sizes, returned
00678  * error-codes, etc. 
00679  *
00680  * this greatly reduces the complexitiy of the migrate-functions.
00681  *
00682  **/
00683 
00684 static BOOL net_spoolss_enum_printers(struct rpc_pipe_client *pipe_hnd,
00685                                         TALLOC_CTX *mem_ctx, 
00686                                         char *name,
00687                                         uint32 flags,
00688                                         uint32 level, 
00689                                         uint32 *num_printers,
00690                                         PRINTER_INFO_CTR *ctr)
00691 {
00692         WERROR result;
00693 
00694         /* enum printers */
00695         result = rpccli_spoolss_enum_printers(pipe_hnd, mem_ctx, name, flags,
00696                 level, num_printers, ctr);
00697 
00698         if (!W_ERROR_IS_OK(result)) {
00699                 printf("cannot enum printers: %s\n", dos_errstr(result));
00700                 return False;
00701         }
00702 
00703         return True;
00704 }
00705 
00706 static BOOL net_spoolss_open_printer_ex(struct rpc_pipe_client *pipe_hnd,
00707                                         TALLOC_CTX *mem_ctx,
00708                                         const char *printername,
00709                                         uint32 access_required, 
00710                                         const char *username,
00711                                         POLICY_HND *hnd)
00712 {
00713         WERROR result;
00714         fstring servername, printername2;
00715 
00716         slprintf(servername, sizeof(servername)-1, "\\\\%s", pipe_hnd->cli->desthost);
00717 
00718         fstrcpy(printername2, servername);
00719         fstrcat(printername2, "\\");
00720         fstrcat(printername2, printername);
00721 
00722         DEBUG(10,("connecting to: %s as %s for %s and access: %x\n", 
00723                 servername, username, printername2, access_required));
00724 
00725         /* open printer */
00726         result = rpccli_spoolss_open_printer_ex(pipe_hnd, mem_ctx, printername2,
00727                         "", access_required,
00728                         servername, username, hnd);
00729 
00730         /* be more verbose */
00731         if (W_ERROR_V(result) == W_ERROR_V(WERR_ACCESS_DENIED)) {
00732                 d_fprintf(stderr, "no access to printer [%s] on [%s] for user [%s] granted\n", 
00733                         printername2, servername, username);
00734                 return False;
00735         }
00736 
00737         if (!W_ERROR_IS_OK(result)) {
00738                 d_fprintf(stderr, "cannot open printer %s on server %s: %s\n", 
00739                         printername2, servername, dos_errstr(result));
00740                 return False;
00741         }
00742 
00743         DEBUG(2,("got printer handle for printer: %s, server: %s\n", 
00744                 printername2, servername));
00745 
00746         return True;
00747 }
00748 
00749 static BOOL net_spoolss_getprinter(struct rpc_pipe_client *pipe_hnd,
00750                                 TALLOC_CTX *mem_ctx,
00751                                 POLICY_HND *hnd,
00752                                 uint32 level, 
00753                                 PRINTER_INFO_CTR *ctr)
00754 {
00755         WERROR result;
00756 
00757         /* getprinter call */
00758         result = rpccli_spoolss_getprinter(pipe_hnd, mem_ctx, hnd, level, ctr);
00759 
00760         if (!W_ERROR_IS_OK(result)) {
00761                 printf("cannot get printer-info: %s\n", dos_errstr(result));
00762                 return False;
00763         }
00764 
00765         return True;
00766 }
00767 
00768 static BOOL net_spoolss_setprinter(struct rpc_pipe_client *pipe_hnd,
00769                                 TALLOC_CTX *mem_ctx,
00770                                 POLICY_HND *hnd,
00771                                 uint32 level, 
00772                                 PRINTER_INFO_CTR *ctr)
00773 {
00774         WERROR result;
00775 
00776         /* setprinter call */
00777         result = rpccli_spoolss_setprinter(pipe_hnd, mem_ctx, hnd, level, ctr, 0);
00778 
00779         if (!W_ERROR_IS_OK(result)) {
00780                 printf("cannot set printer-info: %s\n", dos_errstr(result));
00781                 return False;
00782         }
00783 
00784         return True;
00785 }
00786 
00787 
00788 static BOOL net_spoolss_setprinterdata(struct rpc_pipe_client *pipe_hnd,
00789                                         TALLOC_CTX *mem_ctx,
00790                                         POLICY_HND *hnd,
00791                                         REGISTRY_VALUE *value)
00792 {
00793         WERROR result;
00794         
00795         /* setprinterdata call */
00796         result = rpccli_spoolss_setprinterdata(pipe_hnd, mem_ctx, hnd, value);
00797 
00798         if (!W_ERROR_IS_OK(result)) {
00799                 printf ("unable to set printerdata: %s\n", dos_errstr(result));
00800                 return False;
00801         }
00802 
00803         return True;
00804 }
00805 
00806 
00807 static BOOL net_spoolss_enumprinterkey(struct rpc_pipe_client *pipe_hnd,
00808                                         TALLOC_CTX *mem_ctx,
00809                                         POLICY_HND *hnd,
00810                                         const char *keyname,
00811                                         uint16 **keylist)
00812 {
00813         WERROR result;
00814 
00815         /* enumprinterkey call */
00816         result = rpccli_spoolss_enumprinterkey(pipe_hnd, mem_ctx, hnd, keyname, keylist, NULL);
00817                 
00818         if (!W_ERROR_IS_OK(result)) {
00819                 printf("enumprinterkey failed: %s\n", dos_errstr(result));
00820                 return False;
00821         }
00822         
00823         return True;
00824 }
00825 
00826 static BOOL net_spoolss_enumprinterdataex(struct rpc_pipe_client *pipe_hnd,
00827                                         TALLOC_CTX *mem_ctx,
00828                                         uint32 offered, 
00829                                         POLICY_HND *hnd,
00830                                         const char *keyname, 
00831                                         REGVAL_CTR *ctr) 
00832 {
00833         WERROR result;
00834 
00835         /* enumprinterdataex call */
00836         result = rpccli_spoolss_enumprinterdataex(pipe_hnd, mem_ctx, hnd, keyname, ctr);
00837                         
00838         if (!W_ERROR_IS_OK(result)) {
00839                 printf("enumprinterdataex failed: %s\n", dos_errstr(result));
00840                 return False;
00841         }
00842         
00843         return True;
00844 }
00845 
00846 
00847 static BOOL net_spoolss_setprinterdataex(struct rpc_pipe_client *pipe_hnd,
00848                                         TALLOC_CTX *mem_ctx,
00849                                         POLICY_HND *hnd,
00850                                         char *keyname, 
00851                                         REGISTRY_VALUE *value)
00852 {
00853         WERROR result;
00854 
00855         /* setprinterdataex call */
00856         result = rpccli_spoolss_setprinterdataex(pipe_hnd, mem_ctx, hnd, 
00857                                               keyname, value);
00858         
00859         if (!W_ERROR_IS_OK(result)) {
00860                 printf("could not set printerdataex: %s\n", dos_errstr(result));
00861                 return False;
00862         }
00863         
00864         return True;
00865 }
00866 
00867 static BOOL net_spoolss_enumforms(struct rpc_pipe_client *pipe_hnd,
00868                                 TALLOC_CTX *mem_ctx,
00869                                 POLICY_HND *hnd,
00870                                 int level,
00871                                 uint32 *num_forms,
00872                                 FORM_1 **forms)
00873                                                                                        
00874 {
00875         WERROR result;
00876 
00877         /* enumforms call */
00878         result = rpccli_spoolss_enumforms(pipe_hnd, mem_ctx, hnd, level, num_forms, forms);
00879 
00880         if (!W_ERROR_IS_OK(result)) {
00881                 printf("could not enum forms: %s\n", dos_errstr(result));
00882                 return False;
00883         }
00884         
00885         return True;
00886 }
00887 
00888 static BOOL net_spoolss_enumprinterdrivers (struct rpc_pipe_client *pipe_hnd,
00889                                         TALLOC_CTX *mem_ctx,
00890                                         uint32 level, const char *env,
00891                                         uint32 *num_drivers,
00892                                         PRINTER_DRIVER_CTR *ctr)
00893 {
00894         WERROR result;
00895 
00896         /* enumprinterdrivers call */
00897         result = rpccli_spoolss_enumprinterdrivers(
00898                         pipe_hnd, mem_ctx, level,
00899                         env, num_drivers, ctr);
00900 
00901         if (!W_ERROR_IS_OK(result)) {
00902                 printf("cannot enum drivers: %s\n", dos_errstr(result));
00903                 return False;
00904         }
00905 
00906         return True;
00907 }
00908 
00909 static BOOL net_spoolss_getprinterdriver(struct rpc_pipe_client *pipe_hnd,
00910                              TALLOC_CTX *mem_ctx, 
00911                              POLICY_HND *hnd, uint32 level, 
00912                              const char *env, int version, 
00913                              PRINTER_DRIVER_CTR *ctr)
00914 {
00915         WERROR result;
00916         
00917         /* getprinterdriver call */
00918         result = rpccli_spoolss_getprinterdriver(
00919                         pipe_hnd, mem_ctx, hnd, level,
00920                         env, version, ctr);
00921 
00922         if (!W_ERROR_IS_OK(result)) {
00923                 DEBUG(1,("cannot get driver (for architecture: %s): %s\n", 
00924                         env, dos_errstr(result)));
00925                 if (W_ERROR_V(result) != W_ERROR_V(WERR_UNKNOWN_PRINTER_DRIVER) &&
00926                     W_ERROR_V(result) != W_ERROR_V(WERR_INVALID_ENVIRONMENT)) {
00927                         printf("cannot get driver: %s\n", dos_errstr(result));
00928                 }
00929                 return False;
00930         }
00931 
00932         return True;
00933 }
00934 
00935 
00936 static BOOL net_spoolss_addprinterdriver(struct rpc_pipe_client *pipe_hnd,
00937                              TALLOC_CTX *mem_ctx, uint32 level,
00938                              PRINTER_DRIVER_CTR *ctr)
00939 {
00940         WERROR result;
00941 
00942         /* addprinterdriver call */
00943         result = rpccli_spoolss_addprinterdriver(pipe_hnd, mem_ctx, level, ctr);
00944 
00945         /* be more verbose */
00946         if (W_ERROR_V(result) == W_ERROR_V(WERR_ACCESS_DENIED)) {
00947                 printf("You are not allowed to add drivers\n");
00948                 return False;
00949         }
00950         if (!W_ERROR_IS_OK(result)) {
00951                 printf("cannot add driver: %s\n", dos_errstr(result));
00952                 return False;
00953         }
00954 
00955         return True;
00956 }
00957 
00958 /**
00959  * abstraction function to get uint32 num_printers and PRINTER_INFO_CTR ctr 
00960  * for a single printer or for all printers depending on argc/argv 
00961  **/
00962 
00963 static BOOL get_printer_info(struct rpc_pipe_client *pipe_hnd,
00964                         TALLOC_CTX *mem_ctx, 
00965                         int level,
00966                         int argc,
00967                         const char **argv, 
00968                         uint32 *num_printers,
00969                         PRINTER_INFO_CTR *ctr)
00970 {
00971 
00972         POLICY_HND hnd;
00973 
00974         /* no arguments given, enumerate all printers */
00975         if (argc == 0) {
00976 
00977                 if (!net_spoolss_enum_printers(pipe_hnd, mem_ctx, NULL, 
00978                                 PRINTER_ENUM_LOCAL|PRINTER_ENUM_SHARED, 
00979                                 level, num_printers, ctr)) 
00980                         return False;
00981 
00982                 goto out;
00983         }
00984 
00985 
00986         /* argument given, get a single printer by name */
00987         if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, argv[0],
00988                         MAXIMUM_ALLOWED_ACCESS, pipe_hnd->cli->user_name, &hnd)) 
00989                 return False;
00990 
00991         if (!net_spoolss_getprinter(pipe_hnd, mem_ctx, &hnd, level, ctr)) {
00992                 rpccli_spoolss_close_printer(pipe_hnd, mem_ctx, &hnd);
00993                 return False;
00994         }
00995 
00996         rpccli_spoolss_close_printer(pipe_hnd, mem_ctx, &hnd);
00997 
00998         *num_printers = 1;
00999 
01000 out:
01001         DEBUG(3,("got %d printers\n", *num_printers));
01002 
01003         return True;
01004 
01005 }
01006 
01007 /** 
01008  * List print-queues (including local printers that are not shared)
01009  *
01010  * All parameters are provided by the run_rpc_command function, except for
01011  * argc, argv which are passed through. 
01012  *
01013  * @param domain_sid The domain sid aquired from the remote server
01014  * @param cli A cli_state connected to the server.
01015  * @param mem_ctx Talloc context, destoyed on compleation of the function.
01016  * @param argc  Standard main() style argc
01017  * @param argv  Standard main() style argv.  Initial components are already
01018  *              stripped
01019  *
01020  * @return Normal NTSTATUS return.
01021  **/
01022 
01023 NTSTATUS rpc_printer_list_internals(const DOM_SID *domain_sid,
01024                                         const char *domain_name, 
01025                                         struct cli_state *cli,
01026                                         struct rpc_pipe_client *pipe_hnd,
01027                                         TALLOC_CTX *mem_ctx, 
01028                                         int argc,
01029                                         const char **argv)
01030 {
01031         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
01032         uint32 i, num_printers; 
01033         uint32 level = 2;
01034         pstring printername, sharename;
01035         PRINTER_INFO_CTR ctr;
01036 
01037         printf("listing printers\n");
01038 
01039         if (!get_printer_info(pipe_hnd, mem_ctx, level, argc, argv, &num_printers, &ctr))
01040                 return nt_status;
01041 
01042         for (i = 0; i < num_printers; i++) {
01043 
01044                 /* do some initialization */
01045                 rpcstr_pull(printername, ctr.printers_2[i].printername.buffer, 
01046                         sizeof(printername), -1, STR_TERMINATE);
01047                 rpcstr_pull(sharename, ctr.printers_2[i].sharename.buffer, 
01048                         sizeof(sharename), -1, STR_TERMINATE);
01049                 
01050                 d_printf("printer %d: %s, shared as: %s\n", 
01051                         i+1, printername, sharename);
01052         }
01053 
01054         return NT_STATUS_OK;
01055 }
01056 
01057 /** 
01058  * List printer-drivers from a server 
01059  *
01060  * All parameters are provided by the run_rpc_command function, except for
01061  * argc, argv which are passed through. 
01062  *
01063  * @param domain_sid The domain sid aquired from the remote server
01064  * @param cli A cli_state connected to the server.
01065  * @param mem_ctx Talloc context, destoyed on compleation of the function.
01066  * @param argc  Standard main() style argc
01067  * @param argv  Standard main() style argv.  Initial components are already
01068  *              stripped
01069  *
01070  * @return Normal NTSTATUS return.
01071  **/
01072 
01073 NTSTATUS rpc_printer_driver_list_internals(const DOM_SID *domain_sid,
01074                                                 const char *domain_name, 
01075                                                 struct cli_state *cli,
01076                                                 struct rpc_pipe_client *pipe_hnd,
01077                                                 TALLOC_CTX *mem_ctx, 
01078                                                 int argc,
01079                                                 const char **argv)
01080 {
01081         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
01082         uint32 i;
01083         uint32 level = 3; 
01084         PRINTER_DRIVER_CTR drv_ctr_enum;
01085         int d;
01086         
01087         ZERO_STRUCT(drv_ctr_enum);
01088 
01089         printf("listing printer-drivers\n");
01090 
01091         for (i=0; archi_table[i].long_archi!=NULL; i++) {
01092 
01093                 uint32 num_drivers;
01094 
01095                 /* enum remote drivers */
01096                 if (!net_spoolss_enumprinterdrivers(pipe_hnd, mem_ctx, level,
01097                                 archi_table[i].long_archi, 
01098                                 &num_drivers, &drv_ctr_enum)) {
01099                                                                                 
01100                         nt_status = NT_STATUS_UNSUCCESSFUL;
01101                         goto done;
01102                 }
01103 
01104                 if (num_drivers == 0) {
01105                         d_printf ("no drivers found on server for architecture: [%s].\n", 
01106                                 archi_table[i].long_archi);
01107                         continue;
01108                 } 
01109                 
01110                 d_printf("got %d printer-drivers for architecture: [%s]\n", 
01111                         num_drivers, archi_table[i].long_archi);
01112 
01113 
01114                 /* do something for all drivers for architecture */
01115                 for (d = 0; d < num_drivers; d++) {
01116                         display_print_driver_3(&(drv_ctr_enum.info3[d]));
01117                 }
01118         }
01119         
01120         nt_status = NT_STATUS_OK;
01121 
01122 done:
01123         return nt_status;
01124 
01125 }
01126 
01127 /** 
01128  * Publish print-queues with args-wrapper
01129  *
01130  * @param cli A cli_state connected to the server.
01131  * @param mem_ctx Talloc context, destoyed on compleation of the function.
01132  * @param argc  Standard main() style argc
01133  * @param argv  Standard main() style argv.  Initial components are already
01134  *              stripped
01135  * @param action
01136  *
01137  * @return Normal NTSTATUS return.
01138  **/
01139 
01140 static NTSTATUS rpc_printer_publish_internals_args(struct rpc_pipe_client *pipe_hnd,
01141                                         TALLOC_CTX *mem_ctx, 
01142                                         int argc,
01143                                         const char **argv,
01144                                         uint32 action)
01145 {
01146         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
01147         uint32 i, num_printers; 
01148         uint32 level = 7;
01149         pstring printername, sharename;
01150         PRINTER_INFO_CTR ctr, ctr_pub;
01151         POLICY_HND hnd;
01152         BOOL got_hnd = False;
01153         WERROR result;
01154         const char *action_str;
01155 
01156         if (!get_printer_info(pipe_hnd, mem_ctx, 2, argc, argv, &num_printers, &ctr))
01157                 return nt_status;
01158 
01159         for (i = 0; i < num_printers; i++) {
01160 
01161                 /* do some initialization */
01162                 rpcstr_pull(printername, ctr.printers_2[i].printername.buffer, 
01163                         sizeof(printername), -1, STR_TERMINATE);
01164                 rpcstr_pull(sharename, ctr.printers_2[i].sharename.buffer, 
01165                         sizeof(sharename), -1, STR_TERMINATE);
01166 
01167                 /* open printer handle */
01168                 if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, sharename,
01169                         PRINTER_ALL_ACCESS, pipe_hnd->cli->user_name, &hnd)) 
01170                         goto done;
01171 
01172                 got_hnd = True;
01173 
01174                 /* check for existing dst printer */
01175                 if (!net_spoolss_getprinter(pipe_hnd, mem_ctx, &hnd, level, &ctr_pub)) 
01176                         goto done;
01177 
01178                 /* check action and set string */
01179                 switch (action) {
01180                 case SPOOL_DS_PUBLISH:
01181                         action_str = "published";
01182                         break;
01183                 case SPOOL_DS_UPDATE:
01184                         action_str = "updated";
01185                         break;
01186                 case SPOOL_DS_UNPUBLISH:
01187                         action_str = "unpublished";
01188                         break;
01189                 default:
01190                         action_str = "unknown action";
01191                         printf("unkown action: %d\n", action);
01192                         break;
01193                 }
01194 
01195                 ctr_pub.printers_7->action = action;
01196 
01197                 result = rpccli_spoolss_setprinter(pipe_hnd, mem_ctx, &hnd, level, &ctr_pub, 0);
01198                 if (!W_ERROR_IS_OK(result) && (W_ERROR_V(result) != W_ERROR_V(WERR_IO_PENDING))) {
01199                         printf("cannot set printer-info: %s\n", dos_errstr(result));
01200                         goto done;
01201                 }
01202 
01203                 printf("successfully %s printer %s in Active Directory\n", action_str, sharename);
01204         }
01205 
01206         nt_status = NT_STATUS_OK;
01207 
01208 done:
01209         if (got_hnd) 
01210                 rpccli_spoolss_close_printer(pipe_hnd, mem_ctx, &hnd);
01211         
01212         return nt_status;
01213 }
01214 
01215 NTSTATUS rpc_printer_publish_publish_internals(const DOM_SID *domain_sid,
01216                                                 const char *domain_name, 
01217                                                 struct cli_state *cli,
01218                                                 struct rpc_pipe_client *pipe_hnd,
01219                                                 TALLOC_CTX *mem_ctx, 
01220                                                 int argc,
01221                                                 const char **argv)
01222 {
01223         return rpc_printer_publish_internals_args(pipe_hnd, mem_ctx, argc, argv, SPOOL_DS_PUBLISH);
01224 }
01225 
01226 NTSTATUS rpc_printer_publish_unpublish_internals(const DOM_SID *domain_sid,
01227                                                 const char *domain_name, 
01228                                                 struct cli_state *cli,
01229                                                 struct rpc_pipe_client *pipe_hnd,
01230                                                 TALLOC_CTX *mem_ctx, 
01231                                                 int argc,
01232                                                 const char **argv)
01233 {
01234         return rpc_printer_publish_internals_args(pipe_hnd, mem_ctx, argc, argv, SPOOL_DS_UNPUBLISH);
01235 }
01236 
01237 NTSTATUS rpc_printer_publish_update_internals(const DOM_SID *domain_sid,
01238                                                 const char *domain_name, 
01239                                                 struct cli_state *cli,
01240                                                 struct rpc_pipe_client *pipe_hnd,
01241                                                 TALLOC_CTX *mem_ctx, 
01242                                                 int argc,
01243                                                 const char **argv)
01244 {
01245         return rpc_printer_publish_internals_args(pipe_hnd, mem_ctx, argc, argv, SPOOL_DS_UPDATE);
01246 }
01247 
01248 /** 
01249  * List print-queues w.r.t. their publishing state
01250  *
01251  * All parameters are provided by the run_rpc_command function, except for
01252  * argc, argv which are passed through. 
01253  *
01254  * @param domain_sid The domain sid aquired from the remote server
01255  * @param cli A cli_state connected to the server.
01256  * @param mem_ctx Talloc context, destoyed on compleation of the function.
01257  * @param argc  Standard main() style argc
01258  * @param argv  Standard main() style argv.  Initial components are already
01259  *              stripped
01260  *
01261  * @return Normal NTSTATUS return.
01262  **/
01263 
01264 NTSTATUS rpc_printer_publish_list_internals(const DOM_SID *domain_sid,
01265                                                 const char *domain_name, 
01266                                                 struct cli_state *cli,
01267                                                 struct rpc_pipe_client *pipe_hnd,
01268                                                 TALLOC_CTX *mem_ctx, 
01269                                                 int argc,
01270                                                 const char **argv)
01271 {
01272         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
01273         uint32 i, num_printers; 
01274         uint32 level = 7;
01275         pstring printername, sharename;
01276         pstring guid;
01277         PRINTER_INFO_CTR ctr, ctr_pub;
01278         POLICY_HND hnd;
01279         BOOL got_hnd = False;
01280         int state;
01281 
01282         if (!get_printer_info(pipe_hnd, mem_ctx, 2, argc, argv, &num_printers, &ctr))
01283                 return nt_status;
01284 
01285         for (i = 0; i < num_printers; i++) {
01286 
01287                 ZERO_STRUCT(ctr_pub);
01288 
01289                 /* do some initialization */
01290                 rpcstr_pull(printername, ctr.printers_2[i].printername.buffer, 
01291                         sizeof(printername), -1, STR_TERMINATE);
01292                 rpcstr_pull(sharename, ctr.printers_2[i].sharename.buffer, 
01293                         sizeof(sharename), -1, STR_TERMINATE);
01294 
01295                 /* open printer handle */
01296                 if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, sharename,
01297                         PRINTER_ALL_ACCESS, cli->user_name, &hnd)) 
01298                         goto done;
01299 
01300                 got_hnd = True;
01301 
01302                 /* check for existing dst printer */
01303                 if (!net_spoolss_getprinter(pipe_hnd, mem_ctx, &hnd, level, &ctr_pub)) 
01304                         goto done;
01305 
01306                 rpcstr_pull(guid, ctr_pub.printers_7->guid.buffer, sizeof(guid), -1, STR_TERMINATE);
01307 
01308                 state = ctr_pub.printers_7->action;
01309                 switch (state) {
01310                         case SPOOL_DS_PUBLISH:
01311                                 printf("printer [%s] is published", sharename);
01312                                 if (opt_verbose)
01313                                         printf(", guid: %s", guid);
01314                                 printf("\n");
01315                                 break;
01316                         case SPOOL_DS_UNPUBLISH:
01317                                 printf("printer [%s] is unpublished\n", sharename);
01318                                 break;
01319                         case SPOOL_DS_UPDATE:
01320                                 printf("printer [%s] is currently updating\n", sharename);
01321                                 break;
01322                         default:
01323                                 printf("unkown state: %d\n", state);
01324                                 break;
01325                 }
01326         }
01327 
01328         nt_status = NT_STATUS_OK;
01329 
01330 done:
01331         if (got_hnd) 
01332                 rpccli_spoolss_close_printer(pipe_hnd, mem_ctx, &hnd);
01333         
01334         return nt_status;
01335 }
01336 
01337 /** 
01338  * Migrate Printer-ACLs from a source server to the destination server
01339  *
01340  * All parameters are provided by the run_rpc_command function, except for
01341  * argc, argv which are passed through. 
01342  *
01343  * @param domain_sid The domain sid aquired from the remote server
01344  * @param cli A cli_state connected to the server.
01345  * @param mem_ctx Talloc context, destoyed on compleation of the function.
01346  * @param argc  Standard main() style argc
01347  * @param argv  Standard main() style argv.  Initial components are already
01348  *              stripped
01349  *
01350  * @return Normal NTSTATUS return.
01351  **/
01352 
01353 NTSTATUS rpc_printer_migrate_security_internals(const DOM_SID *domain_sid,
01354                                                 const char *domain_name, 
01355                                                 struct cli_state *cli,
01356                                                 struct rpc_pipe_client *pipe_hnd,
01357                                                 TALLOC_CTX *mem_ctx, 
01358                                                 int argc,
01359                                                 const char **argv)
01360 {
01361         /* TODO: what now, info2 or info3 ? 
01362            convince jerry that we should add clientside setacls level 3 at least
01363         */
01364         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
01365         uint32 i = 0;
01366         uint32 num_printers;
01367         uint32 level = 2;
01368         pstring printername = "", sharename = "";
01369         BOOL got_hnd_src = False;
01370         BOOL got_hnd_dst = False;
01371         struct rpc_pipe_client *pipe_hnd_dst = NULL;
01372         POLICY_HND hnd_src, hnd_dst;
01373         PRINTER_INFO_CTR ctr_src, ctr_dst, ctr_enum;
01374         struct cli_state *cli_dst = NULL;
01375 
01376         ZERO_STRUCT(ctr_src);
01377 
01378         DEBUG(3,("copying printer ACLs\n"));
01379 
01380         /* connect destination PI_SPOOLSS */
01381         nt_status = connect_dst_pipe(&cli_dst, &pipe_hnd_dst, PI_SPOOLSS);
01382         if (!NT_STATUS_IS_OK(nt_status))
01383                 return nt_status;
01384 
01385 
01386         /* enum source printers */
01387         if (!get_printer_info(pipe_hnd, mem_ctx, level, argc, argv, &num_printers, &ctr_enum)) {
01388                 nt_status = NT_STATUS_UNSUCCESSFUL;
01389                 goto done;
01390         }
01391 
01392         if (!num_printers) {
01393                 printf ("no printers found on server.\n");
01394                 nt_status = NT_STATUS_OK;
01395                 goto done;
01396         } 
01397         
01398         /* do something for all printers */
01399         for (i = 0; i < num_printers; i++) {
01400 
01401                 /* do some initialization */
01402                 rpcstr_pull(printername, ctr_enum.printers_2[i].printername.buffer, 
01403                         sizeof(printername), -1, STR_TERMINATE);
01404                 rpcstr_pull(sharename, ctr_enum.printers_2[i].sharename.buffer, 
01405                         sizeof(sharename), -1, STR_TERMINATE);
01406                 /* we can reset NT_STATUS here because we do not 
01407                    get any real NT_STATUS-codes anymore from now on */
01408                 nt_status = NT_STATUS_UNSUCCESSFUL;
01409                 
01410                 d_printf("migrating printer ACLs for:     [%s] / [%s]\n", 
01411                         printername, sharename);
01412 
01413                 /* according to msdn you have specify these access-rights 
01414                    to see the security descriptor
01415                         - READ_CONTROL (DACL)
01416                         - ACCESS_SYSTEM_SECURITY (SACL)
01417                 */
01418 
01419                 /* open src printer handle */
01420                 if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, sharename,
01421                         MAXIMUM_ALLOWED_ACCESS, cli->user_name, &hnd_src)) 
01422                         goto done;
01423 
01424                 got_hnd_src = True;
01425 
01426                 /* open dst printer handle */
01427                 if (!net_spoolss_open_printer_ex(pipe_hnd_dst, mem_ctx, sharename,
01428                         PRINTER_ALL_ACCESS, cli_dst->user_name, &hnd_dst)) 
01429                         goto done;
01430 
01431                 got_hnd_dst = True;
01432 
01433                 /* check for existing dst printer */
01434                 if (!net_spoolss_getprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, level, &ctr_dst)) 
01435                         goto done;
01436 
01437                 /* check for existing src printer */
01438                 if (!net_spoolss_getprinter(pipe_hnd, mem_ctx, &hnd_src, 3, &ctr_src)) 
01439                         goto done;
01440 
01441                 /* Copy Security Descriptor */
01442 
01443                 /* copy secdesc (info level 2) */
01444                 ctr_dst.printers_2->devmode = NULL; 
01445                 ctr_dst.printers_2->secdesc = dup_sec_desc(mem_ctx, ctr_src.printers_3->secdesc);
01446 
01447                 if (opt_verbose)
01448                         display_sec_desc(ctr_dst.printers_2->secdesc);
01449                 
01450                 if (!net_spoolss_setprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, 2, &ctr_dst)) 
01451                         goto done;
01452                 
01453                 DEBUGADD(1,("\tSetPrinter of SECDESC succeeded\n"));
01454 
01455 
01456                 /* close printer handles here */
01457                 if (got_hnd_src) {
01458                         rpccli_spoolss_close_printer(pipe_hnd, mem_ctx, &hnd_src);
01459                         got_hnd_src = False;
01460                 }
01461 
01462                 if (got_hnd_dst) {
01463                         rpccli_spoolss_close_printer(pipe_hnd_dst, mem_ctx, &hnd_dst);
01464                         got_hnd_dst = False;
01465                 }
01466 
01467         }
01468         
01469         nt_status = NT_STATUS_OK;
01470 
01471 done:
01472 
01473         if (got_hnd_src) {
01474                 rpccli_spoolss_close_printer(pipe_hnd, mem_ctx, &hnd_src);
01475         }
01476 
01477         if (got_hnd_dst) {
01478                 rpccli_spoolss_close_printer(pipe_hnd_dst, mem_ctx, &hnd_dst);
01479         }
01480 
01481         if (cli_dst) {
01482                 cli_shutdown(cli_dst);
01483         }
01484         return nt_status;
01485 }
01486 
01487 /** 
01488  * Migrate printer-forms from a src server to the dst server
01489  *
01490  * All parameters are provided by the run_rpc_command function, except for
01491  * argc, argv which are passed through. 
01492  *
01493  * @param domain_sid The domain sid aquired from the remote server
01494  * @param cli A cli_state connected to the server.
01495  * @param mem_ctx Talloc context, destoyed on compleation of the function.
01496  * @param argc  Standard main() style argc
01497  * @param argv  Standard main() style argv.  Initial components are already
01498  *              stripped
01499  *
01500  * @return Normal NTSTATUS return.
01501  **/
01502 
01503 NTSTATUS rpc_printer_migrate_forms_internals(const DOM_SID *domain_sid,
01504                                                 const char *domain_name, 
01505                                                 struct cli_state *cli,
01506                                                 struct rpc_pipe_client *pipe_hnd,
01507                                                 TALLOC_CTX *mem_ctx, 
01508                                                 int argc,
01509                                                 const char **argv)
01510 {
01511         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
01512         WERROR result;
01513         uint32 i, f;
01514         uint32 num_printers;
01515         uint32 level = 1;
01516         pstring printername = "", sharename = "";
01517         BOOL got_hnd_src = False;
01518         BOOL got_hnd_dst = False;
01519         struct rpc_pipe_client *pipe_hnd_dst = NULL;
01520         POLICY_HND hnd_src, hnd_dst;
01521         PRINTER_INFO_CTR ctr_enum, ctr_dst;
01522         uint32 num_forms;
01523         FORM_1 *forms;
01524         struct cli_state *cli_dst = NULL;
01525         
01526         ZERO_STRUCT(ctr_enum);
01527 
01528         DEBUG(3,("copying forms\n"));
01529         
01530         /* connect destination PI_SPOOLSS */
01531         nt_status = connect_dst_pipe(&cli_dst, &pipe_hnd_dst, PI_SPOOLSS);
01532         if (!NT_STATUS_IS_OK(nt_status))
01533                 return nt_status;
01534         
01535 
01536         /* enum src printers */
01537         if (!get_printer_info(pipe_hnd, mem_ctx, 2, argc, argv, &num_printers, &ctr_enum)) {
01538                 nt_status = NT_STATUS_UNSUCCESSFUL;
01539                 goto done;
01540         }
01541 
01542         if (!num_printers) {
01543                 printf ("no printers found on server.\n");
01544                 nt_status = NT_STATUS_OK;
01545                 goto done;
01546         } 
01547         
01548 
01549         /* do something for all printers */
01550         for (i = 0; i < num_printers; i++) {
01551 
01552                 /* do some initialization */
01553                 rpcstr_pull(printername, ctr_enum.printers_2[i].printername.buffer, 
01554                         sizeof(printername), -1, STR_TERMINATE);
01555                 rpcstr_pull(sharename, ctr_enum.printers_2[i].sharename.buffer, 
01556                         sizeof(sharename), -1, STR_TERMINATE);
01557                 /* we can reset NT_STATUS here because we do not 
01558                    get any real NT_STATUS-codes anymore from now on */
01559                 nt_status = NT_STATUS_UNSUCCESSFUL;
01560                 
01561                 d_printf("migrating printer forms for:    [%s] / [%s]\n", 
01562                         printername, sharename);
01563 
01564 
01565                 /* open src printer handle */
01566                 if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, sharename,
01567                         MAXIMUM_ALLOWED_ACCESS, cli->user_name, &hnd_src)) 
01568                         goto done;
01569 
01570                 got_hnd_src = True;
01571 
01572 
01573                 /* open dst printer handle */
01574                 if (!net_spoolss_open_printer_ex(pipe_hnd_dst, mem_ctx, sharename,
01575                         PRINTER_ALL_ACCESS, cli->user_name, &hnd_dst)) 
01576                         goto done;
01577 
01578                 got_hnd_dst = True;
01579 
01580 
01581                 /* check for existing dst printer */
01582                 if (!net_spoolss_getprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, level, &ctr_dst)) 
01583                         goto done;
01584 
01585                 /* finally migrate forms */
01586                 if (!net_spoolss_enumforms(pipe_hnd, mem_ctx, &hnd_src, level, &num_forms, &forms))
01587                         goto done;
01588 
01589                 DEBUG(1,("got %d forms for printer\n", num_forms));
01590 
01591 
01592                 for (f = 0; f < num_forms; f++) {
01593 
01594                         FORM form;
01595                         fstring form_name;
01596                         
01597                         /* only migrate FORM_PRINTER types, according to jerry 
01598                            FORM_BUILTIN-types are hard-coded in samba */
01599                         if (forms[f].flag != FORM_PRINTER)
01600                                 continue;
01601 
01602                         if (forms[f].name.buffer)
01603                                 rpcstr_pull(form_name, forms[f].name.buffer,
01604                                         sizeof(form_name), -1, STR_TERMINATE);
01605 
01606                         if (opt_verbose)
01607                                 d_printf("\tmigrating form # %d [%s] of type [%d]\n", 
01608                                         f, form_name, forms[f].flag);
01609 
01610                         /* is there a more elegant way to do that ? */
01611                         form.flags      = FORM_PRINTER;
01612                         form.size_x     = forms[f].width;
01613                         form.size_y     = forms[f].length;
01614                         form.left       = forms[f].left;
01615                         form.top        = forms[f].top;
01616                         form.right      = forms[f].right;
01617                         form.bottom     = forms[f].bottom;
01618                         
01619                         init_unistr2(&form.name, form_name, UNI_STR_TERMINATE);
01620 
01621                         /* FIXME: there might be something wrong with samba's 
01622                            builtin-forms */
01623                         result = rpccli_spoolss_addform(pipe_hnd_dst, mem_ctx, 
01624                                 &hnd_dst, 1, &form);
01625                         if (!W_ERROR_IS_OK(result)) {
01626                                 d_printf("\tAddForm form %d: [%s] refused.\n", 
01627                                         f, form_name);
01628                                 continue;
01629                         }
01630         
01631                         DEBUGADD(1,("\tAddForm of [%s] succeeded\n", form_name));
01632                 }
01633 
01634 
01635                 /* close printer handles here */
01636                 if (got_hnd_src) {
01637                         rpccli_spoolss_close_printer(pipe_hnd, mem_ctx, &hnd_src);
01638                         got_hnd_src = False;
01639                 }
01640 
01641                 if (got_hnd_dst) {
01642                         rpccli_spoolss_close_printer(pipe_hnd_dst, mem_ctx, &hnd_dst);
01643                         got_hnd_dst = False;
01644                 }
01645         }
01646 
01647         nt_status = NT_STATUS_OK;
01648 
01649 done:
01650 
01651         if (got_hnd_src)
01652                 rpccli_spoolss_close_printer(pipe_hnd, mem_ctx, &hnd_src);
01653 
01654         if (got_hnd_dst)
01655                 rpccli_spoolss_close_printer(pipe_hnd_dst, mem_ctx, &hnd_dst);
01656 
01657         if (cli_dst) {
01658                 cli_shutdown(cli_dst);
01659         }
01660         return nt_status;
01661 }
01662 
01663 /** 
01664  * Migrate printer-drivers from a src server to the dst server
01665  *
01666  * All parameters are provided by the run_rpc_command function, except for
01667  * argc, argv which are passed through. 
01668  *
01669  * @param domain_sid The domain sid aquired from the remote server
01670  * @param cli A cli_state connected to the server.
01671  * @param mem_ctx Talloc context, destoyed on compleation of the function.
01672  * @param argc  Standard main() style argc
01673  * @param argv  Standard main() style argv.  Initial components are already
01674  *              stripped
01675  *
01676  * @return Normal NTSTATUS return.
01677  **/
01678 
01679 NTSTATUS rpc_printer_migrate_drivers_internals(const DOM_SID *domain_sid,
01680                                                 const char *domain_name, 
01681                                                 struct cli_state *cli,
01682                                                 struct rpc_pipe_client *pipe_hnd,
01683                                                 TALLOC_CTX *mem_ctx, 
01684                                                 int argc,
01685                                                 const char **argv)
01686 {
01687         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
01688         uint32 i, p;
01689         uint32 num_printers;
01690         uint32 level = 3; 
01691         pstring printername = "", sharename = "";
01692         BOOL got_hnd_src = False;
01693         BOOL got_hnd_dst = False;
01694         BOOL got_src_driver_share = False;
01695         BOOL got_dst_driver_share = False;
01696         struct rpc_pipe_client *pipe_hnd_dst = NULL;
01697         POLICY_HND hnd_src, hnd_dst;
01698         PRINTER_DRIVER_CTR drv_ctr_src, drv_ctr_dst;
01699         PRINTER_INFO_CTR info_ctr_enum, info_ctr_dst;
01700         struct cli_state *cli_dst = NULL;
01701         struct cli_state *cli_share_src = NULL;
01702         struct cli_state *cli_share_dst = NULL;
01703         fstring drivername = "";
01704         
01705         ZERO_STRUCT(drv_ctr_src);
01706         ZERO_STRUCT(drv_ctr_dst);
01707         ZERO_STRUCT(info_ctr_enum);
01708         ZERO_STRUCT(info_ctr_dst);
01709 
01710 
01711         DEBUG(3,("copying printer-drivers\n"));
01712 
01713         nt_status = connect_dst_pipe(&cli_dst, &pipe_hnd_dst, PI_SPOOLSS);
01714         if (!NT_STATUS_IS_OK(nt_status))
01715                 return nt_status;
01716         
01717 
01718         /* open print$-share on the src server */
01719         nt_status = connect_to_service(&cli_share_src, &cli->dest_ip, 
01720                         cli->desthost, "print$", "A:");
01721         if (!NT_STATUS_IS_OK(nt_status)) 
01722                 goto done;
01723 
01724         got_src_driver_share = True;
01725 
01726 
01727         /* open print$-share on the dst server */
01728         nt_status = connect_to_service(&cli_share_dst, &cli_dst->dest_ip, 
01729                         cli_dst->desthost, "print$", "A:");
01730         if (!NT_STATUS_IS_OK(nt_status)) 
01731                 return nt_status;
01732 
01733         got_dst_driver_share = True;
01734 
01735 
01736         /* enum src printers */
01737         if (!get_printer_info(pipe_hnd, mem_ctx, 2, argc, argv, &num_printers, &info_ctr_enum)) {
01738                 nt_status = NT_STATUS_UNSUCCESSFUL;
01739                 goto done;
01740         }
01741 
01742         if (num_printers == 0) {
01743                 printf ("no printers found on server.\n");
01744                 nt_status = NT_STATUS_OK;
01745                 goto done;
01746         } 
01747         
01748 
01749         /* do something for all printers */
01750         for (p = 0; p < num_printers; p++) {
01751 
01752                 /* do some initialization */
01753                 rpcstr_pull(printername, info_ctr_enum.printers_2[p].printername.buffer, 
01754                         sizeof(printername), -1, STR_TERMINATE);
01755                 rpcstr_pull(sharename, info_ctr_enum.printers_2[p].sharename.buffer, 
01756                         sizeof(sharename), -1, STR_TERMINATE);
01757                 /* we can reset NT_STATUS here because we do not 
01758                    get any real NT_STATUS-codes anymore from now on */
01759                 nt_status = NT_STATUS_UNSUCCESSFUL;
01760 
01761                 d_printf("migrating printer driver for:   [%s] / [%s]\n", 
01762                         printername, sharename);
01763 
01764                 /* open dst printer handle */
01765                 if (!net_spoolss_open_printer_ex(pipe_hnd_dst, mem_ctx, sharename,
01766                         PRINTER_ALL_ACCESS, cli->user_name, &hnd_dst)) 
01767                         goto done;
01768                         
01769                 got_hnd_dst = True;
01770 
01771                 /* check for existing dst printer */
01772                 if (!net_spoolss_getprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, 2, &info_ctr_dst)) 
01773                         goto done;
01774 
01775 
01776                 /* open src printer handle */
01777                 if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, sharename,
01778                         MAXIMUM_ALLOWED_ACCESS, pipe_hnd->cli->user_name, &hnd_src)) 
01779                         goto done;
01780 
01781                 got_hnd_src = True;
01782 
01783 
01784                 /* in a first step call getdriver for each shared printer (per arch)
01785                    to get a list of all files that have to be copied */
01786                    
01787                 for (i=0; archi_table[i].long_archi!=NULL; i++) {
01788 
01789                         /* getdriver src */
01790                         if (!net_spoolss_getprinterdriver(pipe_hnd, mem_ctx, &hnd_src, 
01791                                         level, archi_table[i].long_archi, 
01792                                         archi_table[i].version, &drv_ctr_src)) 
01793                                 continue;
01794 
01795                         rpcstr_pull(drivername, drv_ctr_src.info3->name.buffer, 
01796                                         sizeof(drivername), -1, STR_TERMINATE);
01797 
01798                         if (opt_verbose)
01799                                 display_print_driver_3(drv_ctr_src.info3);
01800 
01801 
01802                         /* check arch dir */
01803                         nt_status = check_arch_dir(cli_share_dst, archi_table[i].short_archi);
01804                         if (!NT_STATUS_IS_OK(nt_status))
01805                                 goto done;
01806 
01807 
01808                         /* copy driver-files */
01809                         nt_status = copy_print_driver_3(mem_ctx, cli_share_src, cli_share_dst, 
01810                                                         archi_table[i].short_archi, 
01811                                                         drv_ctr_src.info3);
01812                         if (!NT_STATUS_IS_OK(nt_status))
01813                                 goto done;
01814 
01815 
01816                         /* adddriver dst */
01817                         if (!net_spoolss_addprinterdriver(pipe_hnd_dst, mem_ctx, level, &drv_ctr_src)) { 
01818                                 nt_status = NT_STATUS_UNSUCCESSFUL;
01819                                 goto done;
01820                         }
01821                                 
01822                         DEBUGADD(1,("Sucessfully added driver [%s] for printer [%s]\n", 
01823                                 drivername, printername));
01824 
01825                 }
01826 
01827                 if (strlen(drivername) == 0) {
01828                         DEBUGADD(1,("Did not get driver for printer %s\n",
01829                                     printername));
01830                         goto done;
01831                 }
01832 
01833                 /* setdriver dst */
01834                 init_unistr(&info_ctr_dst.printers_2->drivername, drivername);
01835                 
01836                 if (!net_spoolss_setprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, 2, &info_ctr_dst)) { 
01837                         nt_status = NT_STATUS_UNSUCCESSFUL;
01838                         goto done;
01839                 }
01840 
01841                 DEBUGADD(1,("Sucessfully set driver %s for printer %s\n", 
01842                         drivername, printername));
01843 
01844                 /* close dst */
01845                 if (got_hnd_dst) {
01846                         rpccli_spoolss_close_printer(pipe_hnd_dst, mem_ctx, &hnd_dst);
01847                         got_hnd_dst = False;
01848                 }
01849 
01850                 /* close src */
01851                 if (got_hnd_src) {
01852                         rpccli_spoolss_close_printer(pipe_hnd, mem_ctx, &hnd_src);
01853                         got_hnd_src = False;
01854                 }
01855         }
01856 
01857         nt_status = NT_STATUS_OK;
01858 
01859 done:
01860 
01861         if (got_hnd_src)
01862                 rpccli_spoolss_close_printer(pipe_hnd, mem_ctx, &hnd_src);
01863 
01864         if (got_hnd_dst)
01865                 rpccli_spoolss_close_printer(pipe_hnd_dst, mem_ctx, &hnd_dst);
01866 
01867         if (cli_dst) {
01868                 cli_shutdown(cli_dst);
01869         }
01870 
01871         if (got_src_driver_share)
01872                 cli_shutdown(cli_share_src);
01873 
01874         if (got_dst_driver_share)
01875                 cli_shutdown(cli_share_dst);
01876 
01877         return nt_status;
01878 
01879 }
01880 
01881 /** 
01882  * Migrate printer-queues from a src to the dst server
01883  * (requires a working "addprinter command" to be installed for the local smbd)
01884  *
01885  * All parameters are provided by the run_rpc_command function, except for
01886  * argc, argv which are passed through. 
01887  *
01888  * @param domain_sid The domain sid aquired from the remote server
01889  * @param cli A cli_state connected to the server.
01890  * @param mem_ctx Talloc context, destoyed on compleation of the function.
01891  * @param argc  Standard main() style argc
01892  * @param argv  Standard main() style argv.  Initial components are already
01893  *              stripped
01894  *
01895  * @return Normal NTSTATUS return.
01896  **/
01897 
01898 NTSTATUS rpc_printer_migrate_printers_internals(const DOM_SID *domain_sid,
01899                                                 const char *domain_name, 
01900                                                 struct cli_state *cli,
01901                                                 struct rpc_pipe_client *pipe_hnd,
01902                                                 TALLOC_CTX *mem_ctx, 
01903                                                 int argc,
01904                                                 const char **argv)
01905 {
01906         WERROR result;
01907         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
01908         uint32 i = 0, num_printers;
01909         uint32 level = 2;
01910         PRINTER_INFO_CTR ctr_src, ctr_dst, ctr_enum;
01911         struct cli_state *cli_dst = NULL;
01912         POLICY_HND hnd_dst, hnd_src;
01913         pstring printername, sharename;
01914         BOOL got_hnd_src = False;
01915         BOOL got_hnd_dst = False;
01916         struct rpc_pipe_client *pipe_hnd_dst = NULL;
01917 
01918         DEBUG(3,("copying printers\n"));
01919 
01920         /* connect destination PI_SPOOLSS */
01921         nt_status = connect_dst_pipe(&cli_dst, &pipe_hnd_dst, PI_SPOOLSS);
01922         if (!NT_STATUS_IS_OK(nt_status))
01923                 return nt_status;
01924 
01925         /* enum printers */
01926         if (!get_printer_info(pipe_hnd, mem_ctx, level, argc, argv, &num_printers, &ctr_enum)) {
01927                 nt_status = NT_STATUS_UNSUCCESSFUL;
01928                 goto done;
01929         }
01930 
01931         if (!num_printers) {
01932                 printf ("no printers found on server.\n");
01933                 nt_status = NT_STATUS_OK;
01934                 goto done;
01935         } 
01936         
01937 
01938         /* do something for all printers */
01939         for (i = 0; i < num_printers; i++) {
01940 
01941                 /* do some initialization */
01942                 rpcstr_pull(printername, ctr_enum.printers_2[i].printername.buffer, 
01943                         sizeof(printername), -1, STR_TERMINATE);
01944                 rpcstr_pull(sharename, ctr_enum.printers_2[i].sharename.buffer, 
01945                         sizeof(sharename), -1, STR_TERMINATE);
01946                 /* we can reset NT_STATUS here because we do not 
01947                    get any real NT_STATUS-codes anymore from now on */
01948                 nt_status = NT_STATUS_UNSUCCESSFUL;
01949                 
01950                 d_printf("migrating printer queue for:    [%s] / [%s]\n", 
01951                         printername, sharename);
01952 
01953                 /* open dst printer handle */
01954                 if (!net_spoolss_open_printer_ex(pipe_hnd_dst, mem_ctx, sharename, 
01955                         PRINTER_ALL_ACCESS, cli->user_name, &hnd_dst)) {
01956                         
01957                         DEBUG(1,("could not open printer: %s\n", sharename));
01958                 } else {
01959                         got_hnd_dst = True;
01960                 }
01961 
01962                 /* check for existing dst printer */
01963                 if (!net_spoolss_getprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, level, &ctr_dst)) {
01964                         printf ("could not get printer, creating printer.\n");
01965                 } else {
01966                         DEBUG(1,("printer already exists: %s\n", sharename));
01967                         /* close printer handle here - dst only, not got src yet. */
01968                         if (got_hnd_dst) {
01969                                 rpccli_spoolss_close_printer(pipe_hnd_dst, mem_ctx, &hnd_dst);
01970                                 got_hnd_dst = False;
01971                         }
01972                         continue;
01973                 }
01974 
01975                 /* now get again src printer ctr via getprinter, 
01976                    we first need a handle for that */
01977 
01978                 /* open src printer handle */
01979                 if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, sharename,
01980                         MAXIMUM_ALLOWED_ACCESS, cli->user_name, &hnd_src)) 
01981                         goto done;
01982 
01983                 got_hnd_src = True;
01984 
01985                 /* getprinter on the src server */
01986                 if (!net_spoolss_getprinter(pipe_hnd, mem_ctx, &hnd_src, level, &ctr_src)) 
01987                         goto done;
01988 
01989                 /* copy each src printer to a dst printer 1:1, 
01990                    maybe some values have to be changed though */
01991                 d_printf("creating printer: %s\n", printername);
01992                 result = rpccli_spoolss_addprinterex (pipe_hnd_dst, mem_ctx, level, &ctr_src);
01993 
01994                 if (W_ERROR_IS_OK(result))
01995                         d_printf ("printer [%s] successfully added.\n", printername);
01996                 else if (W_ERROR_V(result) == W_ERROR_V(WERR_PRINTER_ALREADY_EXISTS)) 
01997                         d_fprintf (stderr, "printer [%s] already exists.\n", printername);
01998                 else {
01999                         d_fprintf (stderr, "could not create printer [%s]\n", printername);
02000                         goto done;
02001                 }
02002 
02003                 /* close printer handles here */
02004                 if (got_hnd_src) {
02005                         rpccli_spoolss_close_printer(pipe_hnd, mem_ctx, &hnd_src);
02006                         got_hnd_src = False;
02007                 }
02008 
02009                 if (got_hnd_dst) {
02010                         rpccli_spoolss_close_printer(pipe_hnd_dst, mem_ctx, &hnd_dst);
02011                         got_hnd_dst = False;
02012                 }
02013         }
02014 
02015         nt_status = NT_STATUS_OK;
02016 
02017 done:
02018         if (got_hnd_src)
02019                 rpccli_spoolss_close_printer(pipe_hnd, mem_ctx, &hnd_src);
02020 
02021         if (got_hnd_dst)
02022                 rpccli_spoolss_close_printer(pipe_hnd_dst, mem_ctx, &hnd_dst);
02023 
02024         if (cli_dst) {
02025                 cli_shutdown(cli_dst);
02026         }
02027         return nt_status;
02028 }
02029 
02030 /** 
02031  * Migrate Printer-Settings from a src server to the dst server
02032  * (for this to work, printers and drivers already have to be migrated earlier)
02033  *
02034  * All parameters are provided by the run_rpc_command function, except for
02035  * argc, argv which are passed through. 
02036  *
02037  * @param domain_sid The domain sid aquired from the remote server
02038  * @param cli A cli_state connected to the server.
02039  * @param mem_ctx Talloc context, destoyed on compleation of the function.
02040  * @param argc  Standard main() style argc
02041  * @param argv  Standard main() style argv.  Initial components are already
02042  *              stripped
02043  *
02044  * @return Normal NTSTATUS return.
02045  **/
02046 
02047 NTSTATUS rpc_printer_migrate_settings_internals(const DOM_SID *domain_sid,
02048                                                 const char *domain_name, 
02049                                                 struct cli_state *cli,
02050                                                 struct rpc_pipe_client *pipe_hnd,
02051                                                 TALLOC_CTX *mem_ctx, 
02052                                                 int argc,
02053                                                 const char **argv)
02054 {
02055 
02056         /* FIXME: Here the nightmare begins */
02057 
02058         WERROR result;
02059         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
02060         uint32 i = 0, p = 0, j = 0;
02061         uint32 num_printers, val_needed, data_needed;
02062         uint32 level = 2;
02063         pstring printername = "", sharename = "";
02064         BOOL got_hnd_src = False;
02065         BOOL got_hnd_dst = False;
02066         struct rpc_pipe_client *pipe_hnd_dst = NULL;
02067         POLICY_HND hnd_src, hnd_dst;
02068         PRINTER_INFO_CTR ctr_enum, ctr_dst, ctr_dst_publish;
02069         REGVAL_CTR *reg_ctr;
02070         struct cli_state *cli_dst = NULL;
02071         char *devicename = NULL, *unc_name = NULL, *url = NULL;
02072         fstring longname;
02073 
02074         uint16 *keylist = NULL, *curkey;
02075 
02076         ZERO_STRUCT(ctr_enum);
02077 
02078         DEBUG(3,("copying printer settings\n"));
02079 
02080         /* connect destination PI_SPOOLSS */
02081         nt_status = connect_dst_pipe(&cli_dst, &pipe_hnd_dst, PI_SPOOLSS);
02082         if (!NT_STATUS_IS_OK(nt_status))
02083                 return nt_status;
02084 
02085 
02086         /* enum src printers */
02087         if (!get_printer_info(pipe_hnd, mem_ctx, level, argc, argv, &num_printers, &ctr_enum)) {
02088                 nt_status = NT_STATUS_UNSUCCESSFUL;
02089                 goto done;
02090         }
02091 
02092         if (!num_printers) {
02093                 printf ("no printers found on server.\n");
02094                 nt_status = NT_STATUS_OK;
02095                 goto done;
02096         } 
02097         
02098 
02099         /* needed for dns-strings in regkeys */
02100         get_mydnsfullname(longname);
02101         
02102         /* do something for all printers */
02103         for (i = 0; i < num_printers; i++) {
02104 
02105                 /* do some initialization */
02106                 rpcstr_pull(printername, ctr_enum.printers_2[i].printername.buffer, 
02107                         sizeof(printername), -1, STR_TERMINATE);
02108                 rpcstr_pull(sharename, ctr_enum.printers_2[i].sharename.buffer, 
02109                         sizeof(sharename), -1, STR_TERMINATE);
02110                 
02111                 /* we can reset NT_STATUS here because we do not 
02112                    get any real NT_STATUS-codes anymore from now on */
02113                 nt_status = NT_STATUS_UNSUCCESSFUL;
02114                 
02115                 d_printf("migrating printer settings for: [%s] / [%s]\n", 
02116                         printername, sharename);
02117 
02118 
02119                 /* open src printer handle */
02120                 if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, sharename,
02121                         MAXIMUM_ALLOWED_ACCESS, cli->user_name, &hnd_src)) 
02122                         goto done;
02123 
02124                 got_hnd_src = True;
02125 
02126 
02127                 /* open dst printer handle */
02128                 if (!net_spoolss_open_printer_ex(pipe_hnd_dst, mem_ctx, sharename,
02129                         PRINTER_ALL_ACCESS, cli_dst->user_name, &hnd_dst)) 
02130                         goto done;
02131 
02132                 got_hnd_dst = True;
02133 
02134 
02135                 /* check for existing dst printer */
02136                 if (!net_spoolss_getprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, 
02137                                 level, &ctr_dst)) 
02138                         goto done;
02139 
02140 
02141                 /* STEP 1: COPY DEVICE-MODE and other 
02142                            PRINTER_INFO_2-attributes
02143                 */
02144 
02145                 ctr_dst.printers_2 = &ctr_enum.printers_2[i];
02146 
02147                 /* why is the port always disconnected when the printer 
02148                    is correctly installed (incl. driver ???) */
02149                 init_unistr( &ctr_dst.printers_2->portname, SAMBA_PRINTER_PORT_NAME);
02150 
02151                 /* check if printer is published */ 
02152                 if (ctr_enum.printers_2[i].attributes & PRINTER_ATTRIBUTE_PUBLISHED) {
02153 
02154                         /* check for existing dst printer */
02155                         if (!net_spoolss_getprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, 7, &ctr_dst_publish))
02156                                 goto done;
02157 
02158                         ctr_dst_publish.printers_7->action = SPOOL_DS_PUBLISH;
02159 
02160                         /* ignore False from setprinter due to WERR_IO_PENDING */
02161                         net_spoolss_setprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, 7, &ctr_dst_publish);
02162 
02163                         DEBUG(3,("republished printer\n"));
02164                 }
02165 
02166                 if (ctr_enum.printers_2[i].devmode != NULL) {
02167 
02168                         /* copy devmode (info level 2) */
02169                         ctr_dst.printers_2->devmode =
02170                                 TALLOC_MEMDUP(mem_ctx,
02171                                               ctr_enum.printers_2[i].devmode,
02172                                               sizeof(DEVICEMODE));
02173 
02174                         /* do not copy security descriptor (we have another
02175                          * command for that) */
02176                         ctr_dst.printers_2->secdesc = NULL;
02177 
02178 #if 0
02179                         if (asprintf(&devicename, "\\\\%s\\%s", longname,
02180                                      printername) < 0) {
02181                                 nt_status = NT_STATUS_NO_MEMORY;
02182                                 goto done;
02183                         }
02184 
02185                         init_unistr(&ctr_dst.printers_2->devmode->devicename,
02186                                     devicename); 
02187 #endif
02188                         if (!net_spoolss_setprinter(pipe_hnd_dst, mem_ctx, &hnd_dst,
02189                                                     level, &ctr_dst)) 
02190                                 goto done;
02191                 
02192                         DEBUGADD(1,("\tSetPrinter of DEVICEMODE succeeded\n"));
02193                 }
02194 
02195                 /* STEP 2: COPY REGISTRY VALUES */
02196         
02197                 /* please keep in mind that samba parse_spools gives horribly 
02198                    crippled results when used to rpccli_spoolss_enumprinterdataex 
02199                    a win2k3-server.  (Bugzilla #1851)
02200                    FIXME: IIRC I've seen it too on a win2k-server 
02201                 */
02202 
02203                 /* enumerate data on src handle */
02204                 result = rpccli_spoolss_enumprinterdata(pipe_hnd, mem_ctx, &hnd_src, p, 0, 0,
02205                         &val_needed, &data_needed, NULL);
02206 
02207                 /* loop for all printerdata of "PrinterDriverData" */
02208                 while (W_ERROR_IS_OK(result)) {
02209                         
02210                         REGISTRY_VALUE value;
02211                         
02212                         result = rpccli_spoolss_enumprinterdata(
02213                                 pipe_hnd, mem_ctx, &hnd_src, p++, val_needed,
02214                                 data_needed, 0, 0, &value);
02215 
02216                         /* loop for all reg_keys */
02217                         if (W_ERROR_IS_OK(result)) {
02218 
02219                                 /* display_value */
02220                                 if (opt_verbose) 
02221                                         display_reg_value(SPOOL_PRINTERDATA_KEY, value);
02222 
02223                                 /* set_value */
02224                                 if (!net_spoolss_setprinterdata(pipe_hnd_dst, mem_ctx, 
02225                                                                 &hnd_dst, &value)) 
02226                                         goto done;
02227 
02228                                 DEBUGADD(1,("\tSetPrinterData of [%s] succeeded\n", 
02229                                         value.valuename));
02230                         }
02231                 }
02232                 
02233                 /* STEP 3: COPY SUBKEY VALUES */
02234 
02235                 /* here we need to enum all printer_keys and then work 
02236                    on the result with enum_printer_key_ex. nt4 does not
02237                    respond to enumprinterkey, win2k does, so continue 
02238                    in case of an error */
02239 
02240                 if (!net_spoolss_enumprinterkey(pipe_hnd, mem_ctx, &hnd_src, "", &keylist)) {
02241                         printf("got no key-data\n");
02242                         continue;
02243                 }
02244 
02245 
02246                 /* work on a list of printer keys 
02247                    each key has to be enumerated to get all required
02248                    information.  information is then set via setprinterdataex-calls */ 
02249 
02250                 if (keylist == NULL)
02251                         continue;
02252 
02253                 curkey = keylist;
02254                 while (*curkey != 0) {
02255 
02256                         pstring subkey;
02257                         rpcstr_pull(subkey, curkey, sizeof(subkey), -1, STR_TERMINATE);
02258 
02259                         curkey += strlen(subkey) + 1;
02260 
02261                         if ( !(reg_ctr = TALLOC_ZERO_P( mem_ctx, REGVAL_CTR )) )
02262                                 return NT_STATUS_NO_MEMORY;
02263 
02264                         /* enumerate all src subkeys */
02265                         if (!net_spoolss_enumprinterdataex(pipe_hnd, mem_ctx, 0, 
02266                                                            &hnd_src, subkey, 
02267                                                            reg_ctr)) 
02268                                 goto done;
02269 
02270                         for (j=0; j < reg_ctr->num_values; j++) {
02271                         
02272                                 REGISTRY_VALUE value;
02273                                 UNISTR2 data;
02274                         
02275                                 /* although samba replies with sane data in most cases we 
02276                                    should try to avoid writing wrong registry data */
02277         
02278                                 if (strequal(reg_ctr->values[j]->valuename, SPOOL_REG_PORTNAME) || 
02279                                     strequal(reg_ctr->values[j]->valuename, SPOOL_REG_UNCNAME) ||
02280                                     strequal(reg_ctr->values[j]->valuename, SPOOL_REG_URL) ||
02281                                     strequal(reg_ctr->values[j]->valuename, SPOOL_REG_SHORTSERVERNAME) ||
02282                                     strequal(reg_ctr->values[j]->valuename, SPOOL_REG_SERVERNAME)) {
02283 
02284                                         if (strequal(reg_ctr->values[j]->valuename, SPOOL_REG_PORTNAME)) {
02285                                 
02286                                                 /* although windows uses a multi-sz, we use a sz */
02287                                                 init_unistr2(&data, SAMBA_PRINTER_PORT_NAME, UNI_STR_TERMINATE);
02288                                                 fstrcpy(value.valuename, SPOOL_REG_PORTNAME);
02289                                         }
02290                                 
02291                                         if (strequal(reg_ctr->values[j]->valuename, SPOOL_REG_UNCNAME)) {
02292                                         
02293                                                 if (asprintf(&unc_name, "\\\\%s\\%s", longname, sharename) < 0) {
02294                                                         nt_status = NT_STATUS_NO_MEMORY;
02295                                                         goto done;
02296                                                 }
02297                                                 init_unistr2(&data, unc_name, UNI_STR_TERMINATE);
02298                                                 fstrcpy(value.valuename, SPOOL_REG_UNCNAME);
02299                                         }
02300 
02301                                         if (strequal(reg_ctr->values[j]->valuename, SPOOL_REG_URL)) {
02302 
02303                                                 continue;
02304 
02305 #if 0
02306                                                 /* FIXME: should we really do that ??? */
02307                                                 if (asprintf(&url, "http://%s:631/printers/%s", longname, sharename) < 0) {
02308                                                         nt_status = NT_STATUS_NO_MEMORY;
02309                                                         goto done;
02310                                                 }
02311                                                 init_unistr2(&data, url, UNI_STR_TERMINATE);
02312                                                 fstrcpy(value.valuename, SPOOL_REG_URL);
02313 #endif
02314                                         }
02315 
02316                                         if (strequal(reg_ctr->values[j]->valuename, SPOOL_REG_SERVERNAME)) {
02317 
02318                                                 init_unistr2(&data, longname, UNI_STR_TERMINATE);
02319                                                 fstrcpy(value.valuename, SPOOL_REG_SERVERNAME);
02320                                         }
02321 
02322                                         if (strequal(reg_ctr->values[j]->valuename, SPOOL_REG_SHORTSERVERNAME)) {
02323 
02324                                                 init_unistr2(&data, global_myname(), UNI_STR_TERMINATE);
02325                                                 fstrcpy(value.valuename, SPOOL_REG_SHORTSERVERNAME);
02326                                         }
02327 
02328                                         value.type = REG_SZ;
02329                                         value.size = data.uni_str_len * 2;
02330                                         if (value.size) {
02331                                                 value.data_p = TALLOC_MEMDUP(mem_ctx, data.buffer, value.size);
02332                                         } else {
02333                                                 value.data_p = NULL;
02334                                         }
02335 
02336                                         if (opt_verbose) 
02337                                                 display_reg_value(subkey, value);
02338 
02339                                         /* here we have to set all subkeys on the dst server */
02340                                         if (!net_spoolss_setprinterdataex(pipe_hnd_dst, mem_ctx, &hnd_dst, 
02341                                                         subkey, &value)) 
02342                                                 goto done;
02343                                                         
02344                                 } else {
02345 
02346                                         if (opt_verbose) 
02347                                                 display_reg_value(subkey, *(reg_ctr->values[j]));
02348 
02349                                         /* here we have to set all subkeys on the dst server */
02350                                         if (!net_spoolss_setprinterdataex(pipe_hnd_dst, mem_ctx, &hnd_dst, 
02351                                                         subkey, reg_ctr->values[j])) 
02352                                                 goto done;
02353 
02354                                 }
02355 
02356                                 DEBUGADD(1,("\tSetPrinterDataEx of key [%s\\%s] succeeded\n", 
02357                                                 subkey, reg_ctr->values[j]->valuename));
02358 
02359                         }
02360 
02361                         TALLOC_FREE( reg_ctr );
02362                 }
02363 
02364                 safe_free(keylist);
02365 
02366                 /* close printer handles here */
02367                 if (got_hnd_src) {
02368                         rpccli_spoolss_close_printer(pipe_hnd, mem_ctx, &hnd_src);
02369                         got_hnd_src = False;
02370                 }
02371 
02372                 if (got_hnd_dst) {
02373                         rpccli_spoolss_close_printer(pipe_hnd_dst, mem_ctx, &hnd_dst);
02374                         got_hnd_dst = False;
02375                 }
02376 
02377         }
02378         
02379         nt_status = NT_STATUS_OK;
02380 
02381 done:
02382         SAFE_FREE(devicename);
02383         SAFE_FREE(url);
02384         SAFE_FREE(unc_name);
02385 
02386         if (got_hnd_src)
02387                 rpccli_spoolss_close_printer(pipe_hnd, mem_ctx, &hnd_src);
02388 
02389         if (got_hnd_dst)
02390                 rpccli_spoolss_close_printer(pipe_hnd_dst, mem_ctx, &hnd_dst);
02391 
02392         if (cli_dst) {
02393                 cli_shutdown(cli_dst);
02394         }
02395         return nt_status;
02396 }

Sambaに対してSat Aug 29 21:23:29 2009に生成されました。  doxygen 1.4.7