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