1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_registry.hxx" 30 31 #include "registry/registry.hxx" 32 #include "registry/reader.hxx" 33 #include "registry/version.h" 34 #include "fileurl.hxx" 35 #include "options.hxx" 36 37 #include <rtl/ustring.hxx> 38 #include <osl/diagnose.h> 39 40 #include <stdio.h> 41 #include <string.h> 42 43 #include <set> 44 #include <vector> 45 #include <string> 46 47 using namespace rtl; 48 using namespace registry::tools; 49 50 typedef std::set< rtl::OUString > StringSet; 51 52 class Options_Impl : public Options 53 { 54 public: 55 explicit Options_Impl(char const * program) 56 : Options(program), 57 m_bFullCheck(false), 58 m_bForceOutput(false), 59 m_bUnoTypeCheck(false), 60 m_checkUnpublished(false) 61 {} 62 63 std::string const & getRegName1() const { return m_regName1; } 64 std::string const & getRegName2() const { return m_regName2; } 65 66 bool isStartKeyValid() const { return (m_startKey.getLength() > 0); } 67 OUString const & getStartKey() const { return m_startKey; } 68 bool matchedWithExcludeKey( const OUString& keyName) const; 69 70 bool fullCheck() const { return m_bFullCheck; } 71 bool forceOutput() const { return m_bForceOutput; } 72 bool unoTypeCheck() const { return m_bUnoTypeCheck; } 73 bool checkUnpublished() const { return m_checkUnpublished; } 74 75 protected: 76 bool setRegName_Impl(char c, std::string const & param); 77 78 virtual void printUsage_Impl() const; 79 virtual bool initOptions_Impl (std::vector< std::string > & rArgs); 80 81 std::string m_regName1; 82 std::string m_regName2; 83 OUString m_startKey; 84 StringSet m_excludeKeys; 85 bool m_bFullCheck; 86 bool m_bForceOutput; 87 bool m_bUnoTypeCheck; 88 bool m_checkUnpublished; 89 }; 90 91 #define U2S( s ) OUStringToOString(s, RTL_TEXTENCODING_UTF8).getStr() 92 93 inline rtl::OUString makeOUString (std::string const & s) 94 { 95 return rtl::OUString(s.c_str(), s.size(), RTL_TEXTENCODING_UTF8, OSTRING_TO_OUSTRING_CVTFLAGS); 96 } 97 98 inline rtl::OUString shortName(rtl::OUString const & fullName) 99 { 100 return fullName.copy(fullName.lastIndexOf('/') + 1); 101 } 102 103 bool Options_Impl::setRegName_Impl(char c, std::string const & param) 104 { 105 bool one = (c == '1'), two = (c == '2'); 106 if (one) 107 m_regName1 = param; 108 if (two) 109 m_regName2 = param; 110 return (one || two); 111 } 112 113 //virtual 114 void Options_Impl::printUsage_Impl() const 115 { 116 std::string const & rProgName = getProgramName(); 117 fprintf(stderr, 118 "Usage: %s -r1<filename> -r2<filename> [-options] | @<filename>\n", rProgName.c_str() 119 ); 120 fprintf(stderr, 121 " -r1<filename> = filename specifies the name of the first registry.\n" 122 " -r2<filename> = filename specifies the name of the second registry.\n" 123 " @<filename> = filename specifies a command file.\n" 124 "Options:\n" 125 " -s<name> = name specifies the name of a start key. If no start key\n" 126 " |S<name> is specified the comparison starts with the root key.\n" 127 " -x<name> = name specifies the name of a key which won't be compared. All\n" 128 " |X<name> subkeys won't be compared also. This option can be used more than once.\n" 129 " -f|F = force the detailed output of any diffenrences. Default\n" 130 " is that only the number of differences is returned.\n" 131 " -c|C = make a complete check, that means any differences will be\n" 132 " detected. Default is only a compatibility check that means\n" 133 " only UNO typelibrary entries will be checked.\n" 134 " -t|T = make an UNO type compatiblity check. This means that registry 2\n" 135 " will be checked against registry 1. If a interface in r2 contains\n" 136 " more methods or the methods are in a different order as in r1, r2 is\n" 137 " incompatible to r1. But if a service in r2 supports more properties as\n" 138 " in r1 and the new properties are 'optional' it is compatible.\n" 139 " -u|U = additionally check types that are unpublished in registry 1.\n" 140 " -h|-? = print this help message and exit.\n" 141 ); 142 fprintf(stderr, 143 "\n%s Version 1.0\n\n", rProgName.c_str() 144 ); 145 } 146 147 // virtual 148 bool Options_Impl::initOptions_Impl (std::vector< std::string > & rArgs) 149 { 150 std::vector< std::string >::const_iterator first = rArgs.begin(), last = rArgs.end(); 151 for (; first != last; ++first) 152 { 153 if ((*first)[0] != '-') 154 { 155 return badOption("invalid", (*first).c_str()); 156 } 157 switch ((*first)[1]) 158 { 159 case 'r': 160 case 'R': 161 { 162 if (!((++first != last) && ((*first)[0] != '-'))) 163 { 164 return badOption("invalid", (*first).c_str()); 165 } 166 167 std::string option(*first), param; 168 if (option.size() == 1) 169 { 170 // "-r<n><space><param>" 171 if (!((++first != last) && ((*first)[0] != '-'))) 172 { 173 return badOption("invalid", (*first).c_str()); 174 } 175 param = (*first); 176 } 177 else 178 { 179 // "-r<n><param>" 180 param = std::string(&(option[1]), option.size() - 1); 181 } 182 if (!setRegName_Impl(option[0], param)) 183 { 184 return badOption("invalid", option.c_str()); 185 } 186 break; 187 } 188 case 's': 189 case 'S': 190 { 191 if (!((++first != last) && ((*first)[0] != '-'))) 192 { 193 return badOption("invalid", (*first).c_str()); 194 } 195 m_startKey = makeOUString(*first); 196 break; 197 } 198 case 'x': 199 case 'X': 200 { 201 if (!((++first != last) && ((*first)[0] != '-'))) 202 { 203 return badOption("invalid", (*first).c_str()); 204 } 205 m_excludeKeys.insert(makeOUString(*first)); 206 break; 207 } 208 case 'f': 209 case 'F': 210 { 211 if ((*first).size() > 2) 212 { 213 return badOption("invalid", (*first).c_str()); 214 } 215 m_bForceOutput = sal_True; 216 break; 217 } 218 case 'c': 219 case 'C': 220 { 221 if ((*first).size() > 2) 222 { 223 return badOption("invalid", (*first).c_str()); 224 } 225 m_bFullCheck = sal_True; 226 break; 227 } 228 case 't': 229 case 'T': 230 { 231 if ((*first).size() > 2) 232 { 233 return badOption("invalid", (*first).c_str()); 234 } 235 m_bUnoTypeCheck = sal_True; 236 break; 237 } 238 case 'u': 239 case 'U': 240 { 241 if ((*first).size() > 2) 242 { 243 return badOption("invalid", (*first).c_str()); 244 } 245 m_checkUnpublished = true; 246 break; 247 } 248 case 'h': 249 case '?': 250 { 251 if ((*first).size() > 2) 252 { 253 return badOption("invalid", (*first).c_str()); 254 } 255 return printUsage(); 256 // break; // Unreachable 257 } 258 default: 259 { 260 return badOption("unknown", (*first).c_str()); 261 // break; // Unreachable 262 } 263 } 264 } 265 266 if ( m_regName1.size() == 0 ) 267 { 268 return badOption("missing", "-r1"); 269 } 270 if ( m_regName2.size() == 0 ) 271 { 272 return badOption("missing", "-r2"); 273 } 274 return true; 275 } 276 277 bool Options_Impl::matchedWithExcludeKey( const OUString& keyName) const 278 { 279 if (!m_excludeKeys.empty()) 280 { 281 StringSet::const_iterator first = m_excludeKeys.begin(), last = m_excludeKeys.end(); 282 for (; first != last; ++first) 283 { 284 if (keyName.indexOf(*first) == 0) 285 return true; 286 } 287 } 288 return false; 289 } 290 291 static char const * getTypeClass(RTTypeClass typeClass) 292 { 293 switch (typeClass) 294 { 295 case RT_TYPE_INTERFACE: 296 return "INTERFACE"; 297 case RT_TYPE_MODULE: 298 return "MODULE"; 299 case RT_TYPE_STRUCT: 300 return "STRUCT"; 301 case RT_TYPE_ENUM: 302 return "ENUM"; 303 case RT_TYPE_EXCEPTION: 304 return "EXCEPTION"; 305 case RT_TYPE_TYPEDEF: 306 return "TYPEDEF"; 307 case RT_TYPE_SERVICE: 308 return "SERVICE"; 309 case RT_TYPE_OBJECT: 310 return "OBJECT"; 311 case RT_TYPE_CONSTANTS: 312 return "CONSTANTS"; 313 default: 314 return "INVALID"; 315 } 316 } 317 318 static OString getFieldAccess(RTFieldAccess fieldAccess) 319 { 320 OString ret; 321 if ( (fieldAccess & RT_ACCESS_INVALID) == RT_ACCESS_INVALID ) 322 { 323 ret += OString("INVALID"); 324 } 325 if ( (fieldAccess & RT_ACCESS_READONLY) == RT_ACCESS_READONLY ) 326 { 327 ret += OString(ret.getLength() > 0 ? ",READONLY" : "READONLY"); 328 } 329 if ( (fieldAccess & RT_ACCESS_OPTIONAL) == RT_ACCESS_OPTIONAL ) 330 { 331 ret += OString(ret.getLength() > 0 ? ",OPTIONAL" : "OPTIONAL"); 332 } 333 if ( (fieldAccess & RT_ACCESS_MAYBEVOID) == RT_ACCESS_MAYBEVOID ) 334 { 335 ret += OString(ret.getLength() > 0 ? ",MAYBEVOID" : "MAYBEVOID"); 336 } 337 if ( (fieldAccess & RT_ACCESS_BOUND) == RT_ACCESS_BOUND ) 338 { 339 ret += OString(ret.getLength() > 0 ? ",BOUND" : "BOUND"); 340 } 341 if ( (fieldAccess & RT_ACCESS_CONSTRAINED) == RT_ACCESS_CONSTRAINED ) 342 { 343 ret += OString(ret.getLength() > 0 ? ",CONSTRAINED" : "CONSTRAINED"); 344 } 345 if ( (fieldAccess & RT_ACCESS_TRANSIENT) == RT_ACCESS_TRANSIENT ) 346 { 347 ret += OString(ret.getLength() > 0 ? ",TRANSIENT" : "TRANSIENT"); 348 } 349 if ( (fieldAccess & RT_ACCESS_MAYBEAMBIGUOUS) == RT_ACCESS_MAYBEAMBIGUOUS ) 350 { 351 ret += OString(ret.getLength() > 0 ? ",MAYBEAMBIGUOUS" : "MAYBEAMBIGUOUS"); 352 } 353 if ( (fieldAccess & RT_ACCESS_MAYBEDEFAULT) == RT_ACCESS_MAYBEDEFAULT ) 354 { 355 ret += OString(ret.getLength() > 0 ? ",MAYBEDEFAULT" : "MAYBEDEFAULT"); 356 } 357 if ( (fieldAccess & RT_ACCESS_REMOVEABLE) == RT_ACCESS_REMOVEABLE ) 358 { 359 ret += OString(ret.getLength() > 0 ? ",REMOVEABLE" : "REMOVEABLE"); 360 } 361 if ( (fieldAccess & RT_ACCESS_ATTRIBUTE) == RT_ACCESS_ATTRIBUTE ) 362 { 363 ret += OString(ret.getLength() > 0 ? ",ATTRIBUTE" : "ATTRIBUTE"); 364 } 365 if ( (fieldAccess & RT_ACCESS_PROPERTY) == RT_ACCESS_PROPERTY ) 366 { 367 ret += OString(ret.getLength() > 0 ? ",PROPERTY" : "PROPERTY"); 368 } 369 if ( (fieldAccess & RT_ACCESS_CONST) == RT_ACCESS_CONST ) 370 { 371 ret += OString(ret.getLength() > 0 ? ",CONST" : "CONST"); 372 } 373 if ( (fieldAccess & RT_ACCESS_READWRITE) == RT_ACCESS_READWRITE ) 374 { 375 ret += OString(ret.getLength() > 0 ? ",READWRITE" : "READWRITE"); 376 } 377 return ret; 378 } 379 380 static char const * getConstValueType(RTConstValue& constValue) 381 { 382 switch (constValue.m_type) 383 { 384 case RT_TYPE_BOOL: 385 return "sal_Bool"; 386 case RT_TYPE_BYTE: 387 return "sal_uInt8"; 388 case RT_TYPE_INT16: 389 return "sal_Int16"; 390 case RT_TYPE_UINT16: 391 return "sal_uInt16"; 392 case RT_TYPE_INT32: 393 return "sal_Int32"; 394 case RT_TYPE_UINT32: 395 return "sal_uInt32"; 396 // case RT_TYPE_INT64: 397 // return "sal_Int64"; 398 // case RT_TYPE_UINT64: 399 // return "sal_uInt64"; 400 case RT_TYPE_FLOAT: 401 return "float"; 402 case RT_TYPE_DOUBLE: 403 return "double"; 404 case RT_TYPE_STRING: 405 return "sal_Unicode*"; 406 default: 407 return "NONE"; 408 } 409 } 410 411 static void printConstValue(RTConstValue& constValue) 412 { 413 switch (constValue.m_type) 414 { 415 case RT_TYPE_NONE: 416 fprintf(stdout, "none"); 417 break; 418 case RT_TYPE_BOOL: 419 fprintf(stdout, "%s", constValue.m_value.aBool ? "TRUE" : "FALSE"); 420 break; 421 case RT_TYPE_BYTE: 422 fprintf(stdout, "%d", constValue.m_value.aByte); 423 break; 424 case RT_TYPE_INT16: 425 fprintf(stdout, "%d", constValue.m_value.aShort); 426 break; 427 case RT_TYPE_UINT16: 428 fprintf(stdout, "%d", constValue.m_value.aUShort); 429 break; 430 case RT_TYPE_INT32: 431 fprintf( 432 stdout, "%ld", 433 sal::static_int_cast< long >(constValue.m_value.aLong)); 434 break; 435 case RT_TYPE_UINT32: 436 fprintf( 437 stdout, "%lu", 438 sal::static_int_cast< unsigned long >( 439 constValue.m_value.aULong)); 440 break; 441 // case RT_TYPE_INT64: 442 // fprintf(stdout, "%d", constValue.m_value.aHyper); 443 // case RT_TYPE_UINT64: 444 // fprintf(stdout, "%d", constValue.m_value.aUHyper); 445 case RT_TYPE_FLOAT: 446 fprintf(stdout, "%f", constValue.m_value.aFloat); 447 break; 448 case RT_TYPE_DOUBLE: 449 fprintf(stdout, "%f", constValue.m_value.aDouble); 450 break; 451 case RT_TYPE_STRING: 452 fprintf( 453 stdout, "%s", 454 (rtl::OUStringToOString( 455 constValue.m_value.aString, RTL_TEXTENCODING_UTF8). 456 getStr())); 457 break; 458 default: 459 break; 460 } 461 } 462 463 static void dumpTypeClass(sal_Bool & rbDump, RTTypeClass typeClass, OUString const & keyName) 464 { 465 if (rbDump) 466 fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName)); 467 rbDump = sal_False; 468 } 469 470 static sal_uInt32 checkConstValue(Options_Impl const & options, 471 const OUString& keyName, 472 RTTypeClass typeClass, 473 sal_Bool & bDump, 474 RTConstValue& constValue1, 475 RTConstValue& constValue2, 476 sal_uInt16 index1) 477 { 478 switch (constValue1.m_type) 479 { 480 case RT_TYPE_INVALID: 481 break; 482 case RT_TYPE_BOOL: 483 if (constValue1.m_value.aBool != constValue2.m_value.aBool) 484 { 485 if ( options.forceOutput() && !options.unoTypeCheck() ) 486 { 487 dumpTypeClass(bDump, typeClass, keyName); 488 fprintf(stdout, " Field %d: Value1 = %s != Value2 = %s\n", index1, 489 constValue1.m_value.aBool ? "TRUE" : "FALSE", 490 constValue2.m_value.aBool ? "TRUE" : "FALSE"); 491 } 492 return 1; 493 } 494 break; 495 case RT_TYPE_BYTE: 496 if (constValue1.m_value.aByte != constValue2.m_value.aByte) 497 { 498 if ( options.forceOutput() && !options.unoTypeCheck() ) 499 { 500 dumpTypeClass(bDump, typeClass, keyName); 501 fprintf(stdout, " Field %d: Value1 = %d != Value2 = %d\n", index1, 502 constValue1.m_value.aByte, constValue2.m_value.aByte); 503 } 504 return 1; 505 } 506 break; 507 case RT_TYPE_INT16: 508 if (constValue1.m_value.aShort != constValue2.m_value.aShort) 509 { 510 if ( options.forceOutput() && !options.unoTypeCheck() ) 511 { 512 dumpTypeClass(bDump, typeClass, keyName); 513 fprintf(stdout, " Field %d: Value1 = %d != Value2 = %d\n", index1, 514 constValue1.m_value.aShort, constValue2.m_value.aShort); 515 } 516 return 1; 517 } 518 break; 519 case RT_TYPE_UINT16: 520 if (constValue1.m_value.aUShort != constValue2.m_value.aUShort) 521 { 522 if ( options.forceOutput() && !options.unoTypeCheck() ) 523 { 524 dumpTypeClass(bDump, typeClass, keyName); 525 fprintf(stdout, " Field %d: Value1 = %d != Value2 = %d\n", index1, 526 constValue1.m_value.aUShort, constValue2.m_value.aUShort); 527 } 528 return 1; 529 } 530 break; 531 case RT_TYPE_INT32: 532 if (constValue1.m_value.aLong != constValue2.m_value.aLong) 533 { 534 if ( options.forceOutput() && !options.unoTypeCheck() ) 535 { 536 dumpTypeClass(bDump, typeClass, keyName); 537 fprintf(stdout, " Field %d: Value1 = %ld != Value2 = %ld\n", index1, 538 sal::static_int_cast< long >(constValue1.m_value.aLong), 539 sal::static_int_cast< long >(constValue2.m_value.aLong)); 540 } 541 return 1; 542 } 543 break; 544 case RT_TYPE_UINT32: 545 if (constValue1.m_value.aULong != constValue2.m_value.aULong) 546 { 547 if ( options.forceOutput() && !options.unoTypeCheck() ) 548 { 549 dumpTypeClass(bDump, typeClass, keyName); 550 fprintf(stdout, " Field %d: Value1 = %lu != Value2 = %lu\n", index1, 551 sal::static_int_cast< unsigned long >(constValue1.m_value.aULong), 552 sal::static_int_cast< unsigned long >(constValue2.m_value.aULong)); 553 } 554 return 1; 555 } 556 break; 557 case RT_TYPE_INT64: 558 if (constValue1.m_value.aHyper != constValue2.m_value.aHyper) 559 { 560 if ( options.forceOutput() && !options.unoTypeCheck() ) 561 { 562 dumpTypeClass(bDump, typeClass, keyName); 563 fprintf( 564 stdout, " Field %d: Value1 = %s != Value2 = %s\n", 565 index1, 566 rtl::OUStringToOString( 567 rtl::OUString::valueOf(constValue1.m_value.aHyper), 568 RTL_TEXTENCODING_ASCII_US).getStr(), 569 rtl::OUStringToOString( 570 rtl::OUString::valueOf(constValue2.m_value.aHyper), 571 RTL_TEXTENCODING_ASCII_US).getStr()); 572 } 573 return 1; 574 } 575 break; 576 case RT_TYPE_UINT64: 577 if (constValue1.m_value.aUHyper != constValue2.m_value.aUHyper) 578 { 579 if ( options.forceOutput() && !options.unoTypeCheck() ) 580 { 581 dumpTypeClass(bDump, typeClass, keyName); 582 fprintf( 583 stdout, " Field %d: Value1 = %s != Value2 = %s\n", 584 index1, 585 rtl::OUStringToOString( 586 rtl::OUString::valueOf( 587 static_cast< sal_Int64 >( 588 constValue1.m_value.aUHyper)), 589 RTL_TEXTENCODING_ASCII_US).getStr(), 590 rtl::OUStringToOString( 591 rtl::OUString::valueOf( 592 static_cast< sal_Int64 >( 593 constValue2.m_value.aUHyper)), 594 RTL_TEXTENCODING_ASCII_US).getStr()); 595 // printing the unsigned values as signed should be 596 // acceptable... 597 } 598 return 1; 599 } 600 break; 601 case RT_TYPE_FLOAT: 602 if (constValue1.m_value.aFloat != constValue2.m_value.aFloat) 603 { 604 if ( options.forceOutput() && !options.unoTypeCheck() ) 605 { 606 dumpTypeClass(bDump, typeClass, keyName); 607 fprintf(stdout, " Field %d: Value1 = %f != Value2 = %f\n", index1, 608 constValue1.m_value.aFloat, constValue2.m_value.aFloat); 609 } 610 return 1; 611 } 612 break; 613 case RT_TYPE_DOUBLE: 614 if (constValue1.m_value.aDouble != constValue2.m_value.aDouble) 615 { 616 if ( options.forceOutput() && !options.unoTypeCheck() ) 617 { 618 dumpTypeClass(bDump, typeClass, keyName); 619 fprintf(stdout, " Field %d: Value1 = %f != Value2 = %f\n", index1, 620 constValue1.m_value.aDouble, constValue2.m_value.aDouble); 621 } 622 return 1; 623 } 624 break; 625 default: 626 OSL_ASSERT(false); 627 break; 628 } 629 return 0; 630 } 631 632 static sal_uInt32 checkField(Options_Impl const & options, 633 const OUString& keyName, 634 RTTypeClass typeClass, 635 sal_Bool & bDump, 636 typereg::Reader& reader1, 637 typereg::Reader& reader2, 638 sal_uInt16 index1, 639 sal_uInt16 index2) 640 { 641 sal_uInt32 nError = 0; 642 if ( reader1.getFieldName(index1) != reader2.getFieldName(index2) ) 643 { 644 if ( options.forceOutput() && !options.unoTypeCheck() ) 645 { 646 dumpTypeClass (bDump, typeClass, keyName); 647 fprintf(stdout, " Field %d: Name1 = %s != Name2 = %s\n", index1, 648 U2S(reader1.getFieldName(index1)), U2S(reader2.getFieldName(index2))); 649 } 650 nError++; 651 } 652 if ( reader1.getFieldTypeName(index1) != reader2.getFieldTypeName(index2) ) 653 { 654 if ( options.forceOutput() && !options.unoTypeCheck() ) 655 { 656 dumpTypeClass (bDump, typeClass, keyName); 657 fprintf(stdout, " Field %d: Type1 = %s != Type2 = %s\n", index1, 658 U2S(reader1.getFieldTypeName(index1)), U2S(reader2.getFieldTypeName(index2))); 659 } 660 nError++; 661 } 662 else 663 { 664 RTConstValue constValue1 = reader1.getFieldValue(index1); 665 RTConstValue constValue2 = reader2.getFieldValue(index2); 666 if ( constValue1.m_type != constValue2.m_type ) 667 { 668 if ( options.forceOutput() && !options.unoTypeCheck() ) 669 { 670 dumpTypeClass (bDump, typeClass, keyName); 671 fprintf(stdout, " Field %d: Access1 = %s != Access2 = %s\n", index1, 672 getConstValueType(constValue1), getConstValueType(constValue2)); 673 fprintf(stdout, " Field %d: Value1 = ", index1); 674 printConstValue(constValue1); 675 fprintf(stdout, " != Value2 = "); 676 printConstValue(constValue1); 677 fprintf(stdout, "\n;"); 678 } 679 nError++; 680 } 681 else 682 { 683 nError += checkConstValue(options, keyName, typeClass, bDump, constValue1, constValue2, index1); 684 } 685 } 686 687 if ( reader1.getFieldFlags(index1) != reader2.getFieldFlags(index2) ) 688 { 689 if ( options.forceOutput() && !options.unoTypeCheck() ) 690 { 691 dumpTypeClass (bDump, typeClass, keyName); 692 fprintf(stdout, " Field %d: FieldAccess1 = %s != FieldAccess2 = %s\n", index1, 693 getFieldAccess(reader1.getFieldFlags(index1)).getStr(), 694 getFieldAccess(reader1.getFieldFlags(index2)).getStr()); 695 } 696 nError++; 697 } 698 699 if ( options.fullCheck() && (reader1.getFieldDocumentation(index1) != reader2.getFieldDocumentation(index2)) ) 700 { 701 if ( options.forceOutput() && !options.unoTypeCheck() ) 702 { 703 dumpTypeClass (bDump, typeClass, keyName); 704 fprintf(stdout, " Field %d: Doku1 = %s\n Doku2 = %s\n", index1, 705 U2S(reader1.getFieldDocumentation(index1)), U2S(reader2.getFieldDocumentation(index2))); 706 } 707 nError++; 708 } 709 return nError; 710 } 711 712 static char const * getMethodMode(RTMethodMode methodMode) 713 { 714 switch ( methodMode ) 715 { 716 case RT_MODE_ONEWAY: 717 return "ONEWAY"; 718 case RT_MODE_ONEWAY_CONST: 719 return "ONEWAY,CONST"; 720 case RT_MODE_TWOWAY: 721 return "NONE"; 722 case RT_MODE_TWOWAY_CONST: 723 return "CONST"; 724 default: 725 return "INVALID"; 726 } 727 } 728 729 static char const * getParamMode(RTParamMode paramMode) 730 { 731 switch ( paramMode ) 732 { 733 case RT_PARAM_IN: 734 return "IN"; 735 case RT_PARAM_OUT: 736 return "OUT"; 737 case RT_PARAM_INOUT: 738 return "INOUT"; 739 default: 740 return "INVALID"; 741 } 742 } 743 744 static sal_uInt32 checkMethod(Options_Impl const & options, 745 const OUString& keyName, 746 RTTypeClass typeClass, 747 sal_Bool & bDump, 748 typereg::Reader& reader1, 749 typereg::Reader& reader2, 750 sal_uInt16 index) 751 { 752 sal_uInt32 nError = 0; 753 if ( reader1.getMethodName(index) != reader2.getMethodName(index) ) 754 { 755 if ( options.forceOutput() ) 756 { 757 dumpTypeClass (bDump, typeClass, keyName); 758 fprintf(stdout, " Method1 %d: Name1 = %s != Name2 = %s\n", index, 759 U2S(reader1.getMethodName(index)), 760 U2S(reader2.getMethodName(index))); 761 } 762 nError++; 763 } 764 765 if ( reader1.getMethodReturnTypeName(index) != reader2.getMethodReturnTypeName(index) ) 766 { 767 if ( options.forceOutput() ) 768 { 769 dumpTypeClass (bDump, typeClass, keyName); 770 fprintf(stdout, " Method1 %d: ReturnType1 = %s != ReturnType2 = %s\n", index, 771 U2S(reader1.getMethodReturnTypeName(index)), 772 U2S(reader2.getMethodReturnTypeName(index))); 773 } 774 nError++; 775 } 776 777 sal_uInt16 nParams1 = (sal_uInt16)reader1.getMethodParameterCount(index); 778 sal_uInt16 nParams2 = (sal_uInt16)reader2.getMethodParameterCount(index); 779 if ( nParams1 != nParams2 ) 780 { 781 if ( options.forceOutput() ) 782 { 783 dumpTypeClass (bDump, typeClass, keyName); 784 fprintf(stdout, " Method %d : nParameters1 = %d != nParameters2 = %d\n", index, nParams1, nParams2); 785 } 786 nError++; 787 } 788 sal_uInt16 i=0; 789 for (i=0; i < nParams1 && i < nParams2; i++) 790 { 791 if ( reader1.getMethodParameterTypeName(index, i) != reader2.getMethodParameterTypeName(index, i) ) 792 { 793 if ( options.forceOutput() ) 794 { 795 dumpTypeClass (bDump, typeClass, keyName); 796 fprintf(stdout, " Method %d, Parameter %d: Type1 = %s != Type2 = %s\n", index, i, 797 U2S(reader1.getMethodParameterTypeName(index, i)), 798 U2S(reader2.getMethodParameterTypeName(index, i))); 799 } 800 nError++; 801 } 802 if ( options.fullCheck() && (reader1.getMethodParameterName(index, i) != reader2.getMethodParameterName(index, i)) ) 803 { 804 if ( options.forceOutput() ) 805 { 806 dumpTypeClass (bDump, typeClass, keyName); 807 fprintf(stdout, " Method %d, Parameter %d: Name1 = %s != Name2 = %s\n", index, i, 808 U2S(reader1.getMethodParameterName(index, i)), 809 U2S(reader2.getMethodParameterName(index, i))); 810 } 811 nError++; 812 } 813 if ( reader1.getMethodParameterFlags(index, i) != reader2.getMethodParameterFlags(index, i) ) 814 { 815 if ( options.forceOutput() ) 816 { 817 dumpTypeClass (bDump, typeClass, keyName); 818 fprintf(stdout, " Method %d, Parameter %d: Mode1 = %s != Mode2 = %s\n", index, i, 819 getParamMode(reader1.getMethodParameterFlags(index, i)), 820 getParamMode(reader2.getMethodParameterFlags(index, i))); 821 } 822 nError++; 823 } 824 } 825 if ( i < nParams1 && options.forceOutput() ) 826 { 827 dumpTypeClass (bDump, typeClass, keyName); 828 fprintf(stdout, " Registry1: Method %d contains %d more parameters\n", index, nParams1 - i); 829 } 830 if ( i < nParams2 && options.forceOutput() ) 831 { 832 dumpTypeClass (bDump, typeClass, keyName); 833 fprintf(stdout, " Registry2: Method %d contains %d more parameters\n", index, nParams2 - i); 834 } 835 836 sal_uInt16 nExcep1 = (sal_uInt16)reader1.getMethodExceptionCount(index); 837 sal_uInt16 nExcep2 = (sal_uInt16)reader2.getMethodExceptionCount(index); 838 if ( nExcep1 != nExcep2 ) 839 { 840 if ( options.forceOutput() ) 841 { 842 dumpTypeClass (bDump, typeClass, keyName); 843 fprintf(stdout, " nExceptions1 = %d != nExceptions2 = %d\n", nExcep1, nExcep2); 844 } 845 nError++; 846 } 847 for (i=0; i < nExcep1 && i < nExcep2; i++) 848 { 849 if ( reader1.getMethodExceptionTypeName(index, i) != reader2.getMethodExceptionTypeName(index, i) ) 850 { 851 if ( options.forceOutput() ) 852 { 853 dumpTypeClass (bDump, typeClass, keyName); 854 fprintf(stdout, " Method %d, Exception %d: Name1 = %s != Name2 = %s\n", index, i, 855 U2S(reader1.getMethodExceptionTypeName(index, i)), 856 U2S(reader2.getMethodExceptionTypeName(index, i))); 857 } 858 nError++; 859 } 860 } 861 if ( i < nExcep1 && options.forceOutput() ) 862 { 863 dumpTypeClass (bDump, typeClass, keyName); 864 fprintf(stdout, " Registry1: Method %d contains %d more exceptions\n", index, nExcep1 - i); 865 } 866 if ( i < nExcep2 && options.forceOutput() ) 867 { 868 dumpTypeClass (bDump, typeClass, keyName); 869 fprintf(stdout, " Registry2: Method %d contains %d more exceptions\n", index, nExcep2 - i); 870 } 871 872 if ( reader1.getMethodFlags(index) != reader2.getMethodFlags(index) ) 873 { 874 if ( options.forceOutput() ) 875 { 876 dumpTypeClass (bDump, typeClass, keyName); 877 fprintf(stdout, " Method %d: Mode1 = %s != Mode2 = %s\n", index, 878 getMethodMode(reader1.getMethodFlags(index)), 879 getMethodMode(reader2.getMethodFlags(index))); 880 } 881 nError++; 882 } 883 884 if ( options.fullCheck() && (reader1.getMethodDocumentation(index) != reader2.getMethodDocumentation(index)) ) 885 { 886 if ( options.forceOutput() ) 887 { 888 dumpTypeClass (bDump, typeClass, keyName); 889 fprintf(stdout, " Method %d: Doku1 = %s\n Doku2 = %s\n", index, 890 U2S(reader1.getMethodDocumentation(index)), 891 U2S(reader2.getMethodDocumentation(index))); 892 } 893 nError++; 894 } 895 return nError; 896 } 897 898 static char const * getReferenceType(RTReferenceType refType) 899 { 900 switch (refType) 901 { 902 case RT_REF_SUPPORTS: 903 return "RT_REF_SUPPORTS"; 904 case RT_REF_OBSERVES: 905 return "RT_REF_OBSERVES"; 906 case RT_REF_EXPORTS: 907 return "RT_REF_EXPORTS"; 908 case RT_REF_NEEDS: 909 return "RT_REF_NEEDS"; 910 default: 911 return "RT_REF_INVALID"; 912 } 913 } 914 915 static sal_uInt32 checkReference(Options_Impl const & options, 916 const OUString& keyName, 917 RTTypeClass typeClass, 918 sal_Bool & bDump, 919 typereg::Reader& reader1, 920 typereg::Reader& reader2, 921 sal_uInt16 index1, 922 sal_uInt16 index2) 923 { 924 sal_uInt32 nError = 0; 925 if ( reader1.getReferenceTypeName(index1) != reader2.getReferenceTypeName(index2) ) 926 { 927 if ( options.forceOutput() && !options.unoTypeCheck() ) 928 { 929 dumpTypeClass (bDump, typeClass, keyName); 930 fprintf(stdout, " Reference %d: Name1 = %s != Name2 = %s\n", index1, 931 U2S(reader1.getReferenceTypeName(index1)), 932 U2S(reader2.getReferenceTypeName(index2))); 933 } 934 nError++; 935 } 936 if ( reader1.getReferenceTypeName(index1) != reader2.getReferenceTypeName(index2) ) 937 { 938 if ( options.forceOutput() && !options.unoTypeCheck() ) 939 { 940 dumpTypeClass (bDump, typeClass, keyName); 941 fprintf(stdout, " Reference %d: Type1 = %s != Type2 = %s\n", index1, 942 getReferenceType(reader1.getReferenceSort(index1)), 943 getReferenceType(reader2.getReferenceSort(index2))); 944 } 945 nError++; 946 } 947 if ( options.fullCheck() && (reader1.getReferenceDocumentation(index1) != reader2.getReferenceDocumentation(index2)) ) 948 { 949 if ( options.forceOutput() && !options.unoTypeCheck() ) 950 { 951 dumpTypeClass (bDump, typeClass, keyName); 952 fprintf(stdout, " Reference %d: Doku1 = %s\n Doku2 = %s\n", index1, 953 U2S(reader1.getReferenceDocumentation(index1)), 954 U2S(reader2.getReferenceDocumentation(index2))); 955 } 956 nError++; 957 } 958 if ( reader1.getReferenceFlags(index1) != reader2.getReferenceFlags(index2) ) 959 { 960 if ( options.forceOutput() && !options.unoTypeCheck() ) 961 { 962 dumpTypeClass (bDump, typeClass, keyName); 963 fprintf(stdout, " Reference %d: Access1 = %s != Access2 = %s\n", index1, 964 getFieldAccess(reader1.getReferenceFlags(index1)).getStr(), 965 getFieldAccess(reader1.getReferenceFlags(index2)).getStr()); 966 } 967 nError++; 968 } 969 return nError; 970 } 971 972 static sal_uInt32 checkFieldsWithoutOrder(Options_Impl const & options, 973 const OUString& keyName, 974 RTTypeClass typeClass, 975 sal_Bool & bDump, 976 typereg::Reader& reader1, 977 typereg::Reader& reader2) 978 { 979 sal_uInt32 nError = 0; 980 981 sal_uInt16 nFields1 = (sal_uInt16)reader1.getFieldCount(); 982 sal_uInt16 nFields2 = (sal_uInt16)reader2.getFieldCount(); 983 sal_uInt16 i=0, j=0; 984 985 if ( nFields1 > nFields2 ) 986 { 987 if ( options.forceOutput() ) 988 { 989 dumpTypeClass (bDump, typeClass, keyName); 990 fprintf(stdout, " %s1 contains %d more properties as %s2\n", 991 getTypeClass(typeClass), nFields1-nFields2, getTypeClass(typeClass)); 992 } 993 } 994 995 sal_Bool bFound = sal_False; 996 ::std::set< sal_uInt16 > moreProps; 997 998 for (i=0; i < nFields1; i++) 999 { 1000 for (j=0; j < nFields2; j++) 1001 { 1002 if (!checkField(options, keyName, typeClass, bDump, reader1, reader2, i, j)) 1003 { 1004 bFound = sal_True; 1005 moreProps.insert(j); 1006 break; 1007 } 1008 } 1009 if (!bFound) 1010 { 1011 if (options.forceOutput()) 1012 { 1013 dumpTypeClass (bDump, typeClass, keyName); 1014 fprintf(stdout, " incompatible change: Field %d ('%s') of r1 is not longer a property of this %s in r2\n", 1015 i, U2S(shortName(reader1.getFieldName(i))), getTypeClass(typeClass)); 1016 } 1017 nError++; 1018 } 1019 else 1020 { 1021 bFound = sal_False; 1022 } 1023 } 1024 1025 if ( typeClass == RT_TYPE_SERVICE && !moreProps.empty() ) 1026 { 1027 for (j=0; j < nFields2; j++) 1028 { 1029 if ( moreProps.find(j) == moreProps.end() ) 1030 { 1031 if ( (reader2.getFieldFlags(j) & RT_ACCESS_OPTIONAL) != RT_ACCESS_OPTIONAL ) 1032 { 1033 if ( options.forceOutput() ) 1034 { 1035 dumpTypeClass (bDump, typeClass, keyName); 1036 fprintf(stdout, 1037 " incompatible change: Field %d ('%s') of r2 is a new property" 1038 " compared to this %s in r1 and is not 'optional'\n", 1039 j, U2S(shortName(reader2.getFieldName(j))), getTypeClass(typeClass)); 1040 } 1041 nError++; 1042 } 1043 } 1044 } 1045 } 1046 1047 return nError; 1048 } 1049 1050 static sal_uInt32 checkBlob( 1051 Options_Impl const & options, 1052 const OUString& keyName, 1053 typereg::Reader& reader1, sal_uInt32 size1, 1054 typereg::Reader& reader2, sal_uInt32 size2) 1055 { 1056 sal_uInt32 nError = 0; 1057 sal_Bool bDump = sal_True; 1058 1059 if ( options.fullCheck() && (size1 != size2) ) 1060 { 1061 if ( options.forceOutput() ) 1062 { 1063 fprintf( 1064 stdout, " Size1 = %lu Size2 = %lu\n", 1065 sal::static_int_cast< unsigned long >(size1), 1066 sal::static_int_cast< unsigned long >(size2)); 1067 } 1068 } 1069 if (reader1.isPublished()) 1070 { 1071 if (!reader2.isPublished()) 1072 { 1073 if (options.forceOutput()) 1074 { 1075 dumpTypeClass(bDump, /*"?"*/ reader1.getTypeClass(), keyName); 1076 fprintf(stdout, " published in 1 but unpublished in 2\n"); 1077 } 1078 ++nError; 1079 } 1080 } 1081 else if (!options.checkUnpublished()) 1082 { 1083 return nError; 1084 } 1085 if ( reader1.getTypeClass() != reader2.getTypeClass() ) 1086 { 1087 if ( options.forceOutput() ) 1088 { 1089 dumpTypeClass(bDump, /*"?"*/ reader1.getTypeClass(), keyName); 1090 fprintf(stdout, " TypeClass1 = %s != TypeClass2 = %s\n", 1091 getTypeClass(reader1.getTypeClass()), 1092 getTypeClass(reader2.getTypeClass())); 1093 } 1094 return ++nError; 1095 } 1096 1097 RTTypeClass typeClass = reader1.getTypeClass(); 1098 if ( reader1.getTypeName() != reader2.getTypeName() ) 1099 { 1100 if ( options.forceOutput() ) 1101 { 1102 dumpTypeClass(bDump, typeClass, keyName); 1103 fprintf(stdout, " TypeName1 = %s != TypeName2 = %s\n", 1104 U2S(reader1.getTypeName()), U2S(reader2.getTypeName())); 1105 } 1106 nError++; 1107 } 1108 if ( (typeClass == RT_TYPE_INTERFACE || 1109 typeClass == RT_TYPE_STRUCT || 1110 typeClass == RT_TYPE_EXCEPTION) ) 1111 { 1112 if (reader1.getSuperTypeCount() != reader2.getSuperTypeCount()) 1113 { 1114 dumpTypeClass(bDump, typeClass, keyName); 1115 fprintf( 1116 stdout, " SuperTypeCount1 = %d != SuperTypeCount2 = %d\n", 1117 static_cast< int >(reader1.getSuperTypeCount()), 1118 static_cast< int >(reader2.getSuperTypeCount())); 1119 ++nError; 1120 } else 1121 { 1122 for (sal_Int16 i = 0; i < reader1.getSuperTypeCount(); ++i) 1123 { 1124 if (reader1.getSuperTypeName(i) != reader2.getSuperTypeName(i)) 1125 { 1126 if ( options.forceOutput() ) 1127 { 1128 dumpTypeClass(bDump, typeClass, keyName); 1129 fprintf(stdout, " SuperTypeName1 = %s != SuperTypeName2 = %s\n", 1130 U2S(reader1.getSuperTypeName(i)), U2S(reader2.getSuperTypeName(i))); 1131 } 1132 nError++; 1133 } 1134 } 1135 } 1136 } 1137 1138 sal_uInt16 nFields1 = (sal_uInt16)reader1.getFieldCount(); 1139 sal_uInt16 nFields2 = (sal_uInt16)reader2.getFieldCount(); 1140 sal_Bool bCheckNormal = sal_True; 1141 1142 if ( (typeClass == RT_TYPE_SERVICE || 1143 typeClass == RT_TYPE_MODULE || 1144 typeClass == RT_TYPE_CONSTANTS) && options.unoTypeCheck() ) 1145 { 1146 bCheckNormal = sal_False; 1147 } 1148 1149 if ( bCheckNormal ) 1150 { 1151 if ( nFields1 != nFields2 ) 1152 { 1153 if ( options.forceOutput() ) 1154 { 1155 dumpTypeClass(bDump, typeClass, keyName); 1156 fprintf(stdout, " nFields1 = %d != nFields2 = %d\n", nFields1, nFields2); 1157 } 1158 nError++; 1159 } 1160 1161 sal_uInt16 i; 1162 for (i=0; i < nFields1 && i < nFields2; i++) 1163 { 1164 nError += checkField(options, keyName, typeClass, bDump, reader1, reader2, i, i); 1165 } 1166 if ( i < nFields1 && options.forceOutput() ) 1167 { 1168 dumpTypeClass(bDump, typeClass, keyName); 1169 fprintf(stdout, " Registry1 contains %d more fields\n", nFields1 - i); 1170 } 1171 if ( i < nFields2 && options.forceOutput() ) 1172 { 1173 dumpTypeClass(bDump, typeClass, keyName); 1174 fprintf(stdout, " Registry2 contains %d more fields\n", nFields2 - i); 1175 } 1176 } 1177 else 1178 { 1179 nError += checkFieldsWithoutOrder(options, keyName, typeClass, bDump, reader1, reader2); 1180 } 1181 1182 if ( typeClass == RT_TYPE_INTERFACE ) 1183 { 1184 sal_uInt16 nMethods1 = (sal_uInt16)reader1.getMethodCount(); 1185 sal_uInt16 nMethods2 = (sal_uInt16)reader2.getMethodCount(); 1186 if ( nMethods1 != nMethods2 ) 1187 { 1188 if ( options.forceOutput() ) 1189 { 1190 dumpTypeClass(bDump, typeClass, keyName); 1191 fprintf(stdout, " nMethods1 = %d != nMethods2 = %d\n", nMethods1, nMethods2); 1192 } 1193 nError++; 1194 } 1195 1196 sal_uInt16 i; 1197 for (i=0; i < nMethods1 && i < nMethods2; i++) 1198 { 1199 nError += checkMethod(options, keyName, typeClass, bDump, reader1, reader2, i); 1200 } 1201 if ( i < nMethods1 && options.forceOutput() ) 1202 { 1203 fprintf(stdout, " Registry1 contains %d more methods\n", nMethods1 - i); 1204 } 1205 if ( i < nMethods2 && options.forceOutput() ) 1206 { 1207 fprintf(stdout, " Registry2 contains %d more methods\n", nMethods2 - i); 1208 } 1209 } 1210 if ( typeClass == RT_TYPE_SERVICE ) 1211 { 1212 sal_uInt16 nReference1 = (sal_uInt16)reader1.getReferenceCount(); 1213 sal_uInt16 nReference2 = (sal_uInt16)reader2.getReferenceCount(); 1214 1215 if ( !bCheckNormal ) 1216 { 1217 sal_uInt16 i=0, j=0; 1218 1219 if ( nReference1 > nReference2 ) 1220 { 1221 if ( options.forceOutput() ) 1222 { 1223 dumpTypeClass(bDump, typeClass, keyName); 1224 fprintf(stdout, " service1 contains %d more references as service2\n", 1225 nReference1-nReference2); 1226 } 1227 } 1228 1229 sal_Bool bFound = sal_False; 1230 ::std::set< sal_uInt16 > moreReferences; 1231 1232 for (i=0; i < nReference1; i++) 1233 { 1234 for (j=0; j < nReference2; j++) 1235 { 1236 if (!checkReference(options, keyName, typeClass, bDump, reader1, reader2, i, j)) 1237 { 1238 bFound = sal_True; 1239 moreReferences.insert(j); 1240 break; 1241 } 1242 } 1243 if (!bFound) 1244 { 1245 if (options.forceOutput()) 1246 { 1247 dumpTypeClass(bDump, typeClass, keyName); 1248 fprintf(stdout, 1249 " incompatible change: Reference %d ('%s') in 'r1' is not longer a reference" 1250 " of this service in 'r2'\n", 1251 i, U2S(shortName(reader1.getReferenceTypeName(i)))); 1252 } 1253 nError++; 1254 } 1255 else 1256 { 1257 bFound = sal_False; 1258 } 1259 } 1260 1261 if ( !moreReferences.empty() ) 1262 { 1263 for (j=0; j < nReference2; j++) 1264 { 1265 if ( moreReferences.find(j) == moreReferences.end() ) 1266 { 1267 if ( (reader2.getReferenceFlags(j) & RT_ACCESS_OPTIONAL) != RT_ACCESS_OPTIONAL ) 1268 { 1269 if ( options.forceOutput() ) 1270 { 1271 dumpTypeClass(bDump, typeClass, keyName); 1272 fprintf(stdout, 1273 " incompatible change: Reference %d ('%s') of r2 is a new reference" 1274 " compared to this service in r1 and is not 'optional'\n", 1275 j, U2S(shortName(reader2.getReferenceTypeName(j)))); 1276 } 1277 nError++; 1278 } 1279 } 1280 } 1281 } 1282 } 1283 else 1284 { 1285 if ( nReference1 != nReference2 ) 1286 { 1287 if ( options.forceOutput() ) 1288 { 1289 dumpTypeClass(bDump, typeClass, keyName); 1290 fprintf(stdout, " nReferences1 = %d != nReferences2 = %d\n", nReference1, nReference2); 1291 } 1292 nError++; 1293 } 1294 1295 sal_uInt16 i; 1296 for (i=0; i < nReference1 && i < nReference2; i++) 1297 { 1298 nError += checkReference(options, keyName, typeClass, bDump, reader1, reader2, i, i); 1299 } 1300 if ( i < nReference1 && options.forceOutput() ) 1301 { 1302 fprintf(stdout, " Registry1 contains %d more references\n", nReference1 - i); 1303 } 1304 if ( i < nReference2 && options.forceOutput() ) 1305 { 1306 fprintf(stdout, " Registry2 contains %d more references\n", nReference2 - i); 1307 } 1308 } 1309 } 1310 1311 if ( options.fullCheck() && (reader1.getDocumentation() != reader2.getDocumentation()) ) 1312 { 1313 if ( options.forceOutput() ) 1314 { 1315 dumpTypeClass(bDump, typeClass, keyName); 1316 fprintf(stdout, " Doku1 = %s\n Doku2 = %s\n", 1317 U2S(reader1.getDocumentation()), U2S(reader2.getDocumentation())); 1318 } 1319 nError++; 1320 } 1321 return nError; 1322 } 1323 1324 static sal_uInt32 checkValueDifference( 1325 Options_Impl const & options, 1326 RegistryKey& key1, RegValueType valueType1, sal_uInt32 size1, 1327 RegistryKey& key2, RegValueType valueType2, sal_uInt32 size2) 1328 { 1329 OUString tmpName; 1330 sal_uInt32 nError = 0; 1331 1332 if ( valueType1 == valueType2 ) 1333 { 1334 sal_Bool bEqual = sal_True; 1335 switch (valueType1) 1336 { 1337 case RG_VALUETYPE_LONGLIST: 1338 { 1339 RegistryValueList<sal_Int32> valueList1; 1340 RegistryValueList<sal_Int32> valueList2; 1341 key1.getLongListValue(tmpName, valueList1); 1342 key2.getLongListValue(tmpName, valueList2); 1343 sal_uInt32 length1 = valueList1.getLength(); 1344 sal_uInt32 length2 = valueList1.getLength(); 1345 if ( length1 != length2 ) 1346 { 1347 bEqual = sal_False; 1348 break; 1349 } 1350 for (sal_uInt32 i=0; i<length1; i++) 1351 { 1352 if ( valueList1.getElement(i) != valueList2.getElement(i) ) 1353 { 1354 bEqual = sal_False; 1355 break; 1356 } 1357 } 1358 } 1359 break; 1360 case RG_VALUETYPE_STRINGLIST: 1361 { 1362 RegistryValueList<sal_Char*> valueList1; 1363 RegistryValueList<sal_Char*> valueList2; 1364 key1.getStringListValue(tmpName, valueList1); 1365 key2.getStringListValue(tmpName, valueList2); 1366 sal_uInt32 length1 = valueList1.getLength(); 1367 sal_uInt32 length2 = valueList1.getLength(); 1368 if ( length1 != length2 ) 1369 { 1370 bEqual = sal_False; 1371 break; 1372 } 1373 for (sal_uInt32 i=0; i<length1; i++) 1374 { 1375 if ( strcmp(valueList1.getElement(i), valueList2.getElement(i)) != 0 ) 1376 { 1377 bEqual = sal_False; 1378 break; 1379 } 1380 } 1381 } 1382 break; 1383 case RG_VALUETYPE_UNICODELIST: 1384 { 1385 RegistryValueList<sal_Unicode*> valueList1; 1386 RegistryValueList<sal_Unicode*> valueList2; 1387 key1.getUnicodeListValue(tmpName, valueList1); 1388 key2.getUnicodeListValue(tmpName, valueList2); 1389 sal_uInt32 length1 = valueList1.getLength(); 1390 sal_uInt32 length2 = valueList1.getLength(); 1391 if ( length1 != length2 ) 1392 { 1393 bEqual = sal_False; 1394 break; 1395 } 1396 for (sal_uInt32 i=0; i<length1; i++) 1397 { 1398 if ( rtl_ustr_compare(valueList1.getElement(i), valueList2.getElement(i)) != 0 ) 1399 { 1400 bEqual = sal_False; 1401 break; 1402 } 1403 } 1404 } 1405 break; 1406 default: 1407 break; 1408 } 1409 1410 if ( bEqual) 1411 { 1412 std::vector< sal_uInt8 > value1(size1); 1413 key1.getValue(tmpName, &value1[0]); 1414 1415 std::vector< sal_uInt8 > value2(size2); 1416 key2.getValue(tmpName, &value2[0]); 1417 1418 bEqual = (rtl_compareMemory(&value1[0], &value2[0], value1.size()) == 0 ); 1419 if ( !bEqual && valueType1 == RG_VALUETYPE_BINARY && valueType2 == RG_VALUETYPE_BINARY ) 1420 { 1421 typereg::Reader reader1(&value1[0], value1.size(), false, TYPEREG_VERSION_1); 1422 typereg::Reader reader2(&value2[0], value2.size(), false, TYPEREG_VERSION_1); 1423 if ( reader1.isValid() && reader2.isValid() ) 1424 { 1425 return checkBlob(options, key1.getName(), reader1, size1, reader2, size2); 1426 } 1427 } 1428 if ( bEqual ) 1429 { 1430 return 0; 1431 } 1432 else 1433 { 1434 if ( options.forceOutput() ) 1435 { 1436 fprintf(stdout, "Difference: key values of key \"%s\" are different\n", U2S(key1.getName())); 1437 } 1438 nError++; 1439 } 1440 } 1441 } 1442 1443 if ( options.forceOutput() ) 1444 { 1445 switch (valueType1) 1446 { 1447 case RG_VALUETYPE_NOT_DEFINED: 1448 fprintf(stdout, " Registry 1: key has no value\n"); 1449 break; 1450 case RG_VALUETYPE_LONG: 1451 { 1452 std::vector< sal_uInt8 > value1(size1); 1453 key1.getValue(tmpName, &value1[0]); 1454 1455 fprintf(stdout, " Registry 1: Value: Type = RG_VALUETYPE_LONG\n"); 1456 fprintf( 1457 stdout, " Size = %lu\n", 1458 sal::static_int_cast< unsigned long >(size1)); 1459 fprintf(stdout, " Data = %p\n", &value1[0]); 1460 } 1461 break; 1462 case RG_VALUETYPE_STRING: 1463 { 1464 std::vector< sal_uInt8 > value1(size1); 1465 key1.getValue(tmpName, &value1[0]); 1466 1467 fprintf(stdout, " Registry 1: Value: Type = RG_VALUETYPE_STRING\n"); 1468 fprintf( 1469 stdout, " Size = %lu\n", 1470 sal::static_int_cast< unsigned long >(size1)); 1471 fprintf(stdout, " Data = \"%s\"\n", reinterpret_cast<char const*>(&value1[0])); 1472 } 1473 break; 1474 case RG_VALUETYPE_UNICODE: 1475 { 1476 std::vector< sal_uInt8 > value1(size1); 1477 key1.getValue(tmpName, &value1[0]); 1478 1479 OUString uStrValue(reinterpret_cast<sal_Unicode const*>(&value1[0])); 1480 fprintf(stdout, " Registry 1: Value: Type = RG_VALUETYPE_UNICODE\n"); 1481 fprintf( 1482 stdout, " Size = %lu\n", 1483 sal::static_int_cast< unsigned long >(size1)); 1484 fprintf(stdout, " Data = \"%s\"\n", U2S(uStrValue)); 1485 } 1486 break; 1487 case RG_VALUETYPE_BINARY: 1488 fprintf(stdout, " Registry 1: Value: Type = RG_VALUETYPE_BINARY\n"); 1489 break; 1490 case RG_VALUETYPE_LONGLIST: 1491 { 1492 RegistryValueList<sal_Int32> valueList; 1493 key1.getLongListValue(tmpName, valueList); 1494 fprintf(stdout, " Registry 1: Value: Type = RG_VALUETYPE_LONGLIST\n"); 1495 fprintf( 1496 stdout, " Size = %lu\n", 1497 sal::static_int_cast< unsigned long >(size1)); 1498 sal_uInt32 length = valueList.getLength(); 1499 for (sal_uInt32 i=0; i<length; i++) 1500 { 1501 fprintf( 1502 stdout, " Data[%lu] = %ld\n", 1503 sal::static_int_cast< unsigned long >(i), 1504 sal::static_int_cast< long >(valueList.getElement(i))); 1505 } 1506 } 1507 break; 1508 case RG_VALUETYPE_STRINGLIST: 1509 { 1510 RegistryValueList<sal_Char*> valueList; 1511 key1.getStringListValue(tmpName, valueList); 1512 fprintf(stdout, " Registry 1: Value: Type = RG_VALUETYPE_STRINGLIST\n"); 1513 fprintf( 1514 stdout, " Size = %lu\n", 1515 sal::static_int_cast< unsigned long >(size1)); 1516 sal_uInt32 length = valueList.getLength(); 1517 for (sal_uInt32 i=0; i<length; i++) 1518 { 1519 fprintf( 1520 stdout, " Data[%lu] = \"%s\"\n", 1521 sal::static_int_cast< unsigned long >(i), 1522 valueList.getElement(i)); 1523 } 1524 } 1525 break; 1526 case RG_VALUETYPE_UNICODELIST: 1527 { 1528 RegistryValueList<sal_Unicode*> valueList; 1529 key1.getUnicodeListValue(tmpName, valueList); 1530 fprintf(stdout, " Registry 1: Value: Type = RG_VALUETYPE_UNICODELIST\n"); 1531 fprintf( 1532 stdout, " Size = %lu\n", 1533 sal::static_int_cast< unsigned long >(size1)); 1534 sal_uInt32 length = valueList.getLength(); 1535 OUString uStrValue; 1536 for (sal_uInt32 i=0; i<length; i++) 1537 { 1538 uStrValue = OUString(valueList.getElement(i)); 1539 fprintf( 1540 stdout, " Data[%lu] = \"%s\"\n", 1541 sal::static_int_cast< unsigned long >(i), U2S(uStrValue)); 1542 } 1543 } 1544 break; 1545 } 1546 1547 switch (valueType2) 1548 { 1549 case RG_VALUETYPE_NOT_DEFINED: 1550 fprintf(stdout, " Registry 2: key has no value\n"); 1551 break; 1552 case RG_VALUETYPE_LONG: 1553 { 1554 std::vector< sal_uInt8 > value2(size2); 1555 key2.getValue(tmpName, &value2[0]); 1556 1557 fprintf(stdout, " Registry 2: Value: Type = RG_VALUETYPE_LONG\n"); 1558 fprintf( 1559 stdout, " Size = %lu\n", 1560 sal::static_int_cast< unsigned long >(size2)); 1561 fprintf(stdout, " Data = %p\n", &value2[0]); 1562 } 1563 break; 1564 case RG_VALUETYPE_STRING: 1565 { 1566 std::vector< sal_uInt8 > value2(size2); 1567 key2.getValue(tmpName, &value2[0]); 1568 1569 fprintf(stdout, " Registry 2: Value: Type = RG_VALUETYPE_STRING\n"); 1570 fprintf( 1571 stdout, " Size = %lu\n", 1572 sal::static_int_cast< unsigned long >(size2)); 1573 fprintf(stdout, " Data = \"%s\"\n", reinterpret_cast<char const*>(&value2[0])); 1574 } 1575 break; 1576 case RG_VALUETYPE_UNICODE: 1577 { 1578 std::vector< sal_uInt8 > value2(size2); 1579 key2.getValue(tmpName, &value2[0]); 1580 1581 OUString uStrValue(reinterpret_cast<sal_Unicode const*>(&value2[0])); 1582 fprintf(stdout, " Registry 2: Value: Type = RG_VALUETYPE_UNICODE\n"); 1583 fprintf( 1584 stdout, " Size = %lu\n", 1585 sal::static_int_cast< unsigned long >(size2)); 1586 fprintf(stdout, " Data = \"%s\"\n", U2S(uStrValue)); 1587 } 1588 break; 1589 case RG_VALUETYPE_BINARY: 1590 fprintf(stdout, " Registry 2: Value: Type = RG_VALUETYPE_BINARY\n"); 1591 break; 1592 case RG_VALUETYPE_LONGLIST: 1593 { 1594 RegistryValueList<sal_Int32> valueList; 1595 key2.getLongListValue(tmpName, valueList); 1596 fprintf(stdout, " Registry 2: Value: Type = RG_VALUETYPE_LONGLIST\n"); 1597 fprintf( 1598 stdout, " Size = %lu\n", 1599 sal::static_int_cast< unsigned long >(size2)); 1600 sal_uInt32 length = valueList.getLength(); 1601 for (sal_uInt32 i=0; i<length; i++) 1602 { 1603 fprintf( 1604 stdout, " Data[%lu] = %ld\n", 1605 sal::static_int_cast< unsigned long >(i), 1606 sal::static_int_cast< long >(valueList.getElement(i))); 1607 } 1608 } 1609 break; 1610 case RG_VALUETYPE_STRINGLIST: 1611 { 1612 RegistryValueList<sal_Char*> valueList; 1613 key2.getStringListValue(tmpName, valueList); 1614 fprintf(stdout, " Registry 2: Value: Type = RG_VALUETYPE_STRINGLIST\n"); 1615 fprintf( 1616 stdout, " Size = %lu\n", 1617 sal::static_int_cast< unsigned long >(size2)); 1618 sal_uInt32 length = valueList.getLength(); 1619 for (sal_uInt32 i=0; i<length; i++) 1620 { 1621 fprintf( 1622 stdout, " Data[%lu] = \"%s\"\n", 1623 sal::static_int_cast< unsigned long >(i), 1624 valueList.getElement(i)); 1625 } 1626 } 1627 break; 1628 case RG_VALUETYPE_UNICODELIST: 1629 { 1630 RegistryValueList<sal_Unicode*> valueList; 1631 key2.getUnicodeListValue(tmpName, valueList); 1632 fprintf(stdout, " Registry 2: Value: Type = RG_VALUETYPE_UNICODELIST\n"); 1633 fprintf( 1634 stdout, " Size = %lu\n", 1635 sal::static_int_cast< unsigned long >(size2)); 1636 sal_uInt32 length = valueList.getLength(); 1637 OUString uStrValue; 1638 for (sal_uInt32 i=0; i<length; i++) 1639 { 1640 uStrValue = OUString(valueList.getElement(i)); 1641 fprintf( 1642 stdout, " Data[%lu] = \"%s\"\n", 1643 sal::static_int_cast< unsigned long >(i), U2S(uStrValue)); 1644 } 1645 } 1646 break; 1647 } 1648 } 1649 return nError; 1650 } 1651 1652 static bool hasPublishedChildren(Options_Impl const & options, RegistryKey & key) 1653 { 1654 RegistryKeyNames subKeyNames; 1655 key.getKeyNames(rtl::OUString(), subKeyNames); 1656 for (sal_uInt32 i = 0; i < subKeyNames.getLength(); ++i) 1657 { 1658 rtl::OUString keyName(subKeyNames.getElement(i)); 1659 if (!options.matchedWithExcludeKey(keyName)) 1660 { 1661 keyName = keyName.copy(keyName.lastIndexOf('/') + 1); 1662 RegistryKey subKey; 1663 if (!key.openKey(keyName, subKey)) 1664 { 1665 if (options.forceOutput()) 1666 { 1667 fprintf( 1668 stdout, 1669 ("WARNING: could not open key \"%s\" in registry" 1670 " \"%s\"\n"), 1671 U2S(subKeyNames.getElement(i)), 1672 options.getRegName1().c_str()); 1673 } 1674 } 1675 if (subKey.isValid()) 1676 { 1677 RegValueType type; 1678 sal_uInt32 size; 1679 if (subKey.getValueInfo(rtl::OUString(), &type, &size) != REG_NO_ERROR) 1680 { 1681 if (options.forceOutput()) 1682 { 1683 fprintf( 1684 stdout, 1685 ("WARNING: could not read key \"%s\" in registry" 1686 " \"%s\"\n"), 1687 U2S(subKeyNames.getElement(i)), 1688 options.getRegName1().c_str()); 1689 } 1690 } 1691 else if (type == RG_VALUETYPE_BINARY) 1692 { 1693 bool published = false; 1694 std::vector< sal_uInt8 > value(size); 1695 if (subKey.getValue(rtl::OUString(), &value[0]) != REG_NO_ERROR) 1696 { 1697 if (options.forceOutput()) 1698 { 1699 fprintf( 1700 stdout, 1701 ("WARNING: could not read key \"%s\" in" 1702 " registry \"%s\"\n"), 1703 U2S(subKeyNames.getElement(i)), 1704 options.getRegName1().c_str()); 1705 } 1706 } 1707 else 1708 { 1709 published = typereg::Reader(&value[0], value.size(), false, TYPEREG_VERSION_1).isPublished(); 1710 } 1711 if (published) 1712 { 1713 return true; 1714 } 1715 } 1716 } 1717 } 1718 } 1719 return false; 1720 } 1721 1722 static sal_uInt32 checkDifferences( 1723 Options_Impl const & options, 1724 RegistryKey& key, StringSet& keys, 1725 RegistryKeyNames& subKeyNames1, 1726 RegistryKeyNames& subKeyNames2) 1727 { 1728 sal_uInt32 nError = 0; 1729 sal_uInt32 length1 = subKeyNames1.getLength(); 1730 sal_uInt32 length2 = subKeyNames2.getLength(); 1731 sal_uInt32 i,j; 1732 1733 for (i=0; i<length1; i++) 1734 { 1735 sal_Bool bFound = sal_False; 1736 for (j=0; j<length2; j++) 1737 { 1738 if ( subKeyNames1.getElement(i) == subKeyNames2.getElement(j) ) 1739 { 1740 bFound = sal_True; 1741 keys.insert(subKeyNames1.getElement(i)); 1742 break; 1743 } 1744 } 1745 if ( !bFound ) 1746 { 1747 if ( options.fullCheck() ) 1748 { 1749 if ( options.forceOutput() ) 1750 { 1751 fprintf(stdout, "EXISTENCE: key \"%s\" exists only in registry \"%s\"\n", 1752 U2S(subKeyNames1.getElement(i)), options.getRegName1().c_str()); 1753 } 1754 nError++; 1755 } 1756 else 1757 { 1758 rtl::OUString keyName(subKeyNames1.getElement(i)); 1759 if (!options.matchedWithExcludeKey(keyName)) 1760 { 1761 keyName = keyName.copy(keyName.lastIndexOf('/') + 1); 1762 RegistryKey subKey; 1763 if (key.openKey(keyName, subKey)) 1764 { 1765 if (options.forceOutput()) 1766 { 1767 fprintf( 1768 stdout, 1769 ("ERROR: could not open key \"%s\" in registry" 1770 " \"%s\"\n"), 1771 U2S(subKeyNames1.getElement(i)), 1772 options.getRegName1().c_str()); 1773 } 1774 ++nError; 1775 } 1776 if (subKey.isValid()) 1777 { 1778 RegValueType type; 1779 sal_uInt32 size; 1780 if (subKey.getValueInfo(rtl::OUString(), &type, &size) != REG_NO_ERROR) 1781 { 1782 if (options.forceOutput()) 1783 { 1784 fprintf( 1785 stdout, 1786 ("ERROR: could not read key \"%s\" in" 1787 " registry \"%s\"\n"), 1788 U2S(subKeyNames1.getElement(i)), 1789 options.getRegName1().c_str()); 1790 } 1791 ++nError; 1792 } 1793 else if (type == RG_VALUETYPE_BINARY) 1794 { 1795 std::vector< sal_uInt8 > value(size); 1796 if (subKey.getValue(rtl::OUString(), &value[0]) != REG_NO_ERROR) 1797 { 1798 if (options.forceOutput()) 1799 { 1800 fprintf( 1801 stdout, 1802 ("ERROR: could not read key \"%s\" in" 1803 " registry \"%s\"\n"), 1804 U2S(subKeyNames1.getElement(i)), 1805 options.getRegName1().c_str()); 1806 } 1807 ++nError; 1808 } 1809 else 1810 { 1811 typereg::Reader reader(&value[0], value.size(), false, TYPEREG_VERSION_1); 1812 if (reader.getTypeClass() == RT_TYPE_MODULE) 1813 { 1814 if (options.checkUnpublished() || hasPublishedChildren(options, subKey)) 1815 { 1816 if (options.forceOutput()) 1817 { 1818 fprintf( 1819 stdout, 1820 ("EXISTENCE: module \"%s\"" 1821 " %sexists only in registry" 1822 " 1\n"), 1823 U2S(subKeyNames1.getElement(i)), 1824 (options.checkUnpublished() 1825 ? "" 1826 : "with published children ")); 1827 } 1828 ++nError; 1829 } 1830 } 1831 else if (options.checkUnpublished() || reader.isPublished()) 1832 { 1833 if (options.forceOutput()) 1834 { 1835 fprintf( 1836 stdout, 1837 ("EXISTENCE: %spublished key \"%s\"" 1838 " exists only in registry 1\n"), 1839 reader.isPublished() ? "" : "un", 1840 U2S(subKeyNames1.getElement(i))); 1841 } 1842 ++nError; 1843 } 1844 } 1845 } 1846 } 1847 } 1848 } 1849 } 1850 } 1851 1852 for (i=0; i<length2; i++) 1853 { 1854 sal_Bool bFound = sal_False; 1855 for (j=0; j<length1; j++) 1856 { 1857 if ( subKeyNames2.getElement(i) == subKeyNames1.getElement(j) ) 1858 { 1859 bFound = sal_True; 1860 keys.insert(subKeyNames2.getElement(i)); 1861 break; 1862 } 1863 } 1864 if ( !bFound && options.fullCheck() ) 1865 { 1866 if ( options.forceOutput() ) 1867 { 1868 fprintf(stdout, "EXISTENCE: key \"%s\" exists only in registry \"%s\"\n", 1869 U2S(subKeyNames2.getElement(i)), options.getRegName2().c_str()); 1870 } 1871 nError++; 1872 } 1873 } 1874 return nError; 1875 } 1876 1877 static sal_uInt32 compareKeys( 1878 Options_Impl const & options, 1879 RegistryKey& key1, 1880 RegistryKey& key2) 1881 { 1882 sal_uInt32 nError = 0; 1883 1884 RegValueType valueType1 = RG_VALUETYPE_NOT_DEFINED; 1885 RegValueType valueType2 = RG_VALUETYPE_NOT_DEFINED; 1886 sal_uInt32 size1 = 0; 1887 sal_uInt32 size2 = 0; 1888 1889 OUString tmpName; 1890 RegError e1 = key1.getValueInfo(tmpName, &valueType1, &size1); 1891 RegError e2 = key2.getValueInfo(tmpName, &valueType2, &size2); 1892 if ( (e1 == e2) && (e1 != REG_VALUE_NOT_EXISTS) && (e1 != REG_INVALID_VALUE) ) 1893 { 1894 nError += checkValueDifference(options, key1, valueType1, size1, key2, valueType2, size2); 1895 } 1896 else 1897 { 1898 if ( (e1 != REG_INVALID_VALUE) || (e2 != REG_INVALID_VALUE) ) 1899 { 1900 if ( options.forceOutput() ) 1901 { 1902 fprintf(stdout, "VALUES: key values of key \"%s\" are different\n", U2S(key1.getName())); 1903 } 1904 nError++; 1905 } 1906 } 1907 1908 RegistryKeyNames subKeyNames1; 1909 RegistryKeyNames subKeyNames2; 1910 1911 key1.getKeyNames(tmpName, subKeyNames1); 1912 key2.getKeyNames(tmpName, subKeyNames2); 1913 1914 StringSet keys; 1915 nError += checkDifferences(options, key1, keys, subKeyNames1, subKeyNames2); 1916 1917 StringSet::iterator iter = keys.begin(); 1918 StringSet::iterator end = keys.end(); 1919 1920 while ( iter != end ) 1921 { 1922 OUString keyName(*iter); 1923 if ( options.matchedWithExcludeKey(keyName) ) 1924 { 1925 ++iter; 1926 continue; 1927 } 1928 1929 sal_Int32 nPos = keyName.lastIndexOf( '/' ); 1930 keyName = keyName.copy( nPos != -1 ? nPos+1 : 0 ); 1931 1932 RegistryKey subKey1; 1933 if ( key1.openKey(keyName, subKey1) ) 1934 { 1935 if ( options.forceOutput() ) 1936 { 1937 fprintf(stdout, "ERROR: could not open key \"%s\" in registry \"%s\"\n", 1938 U2S(*iter), options.getRegName1().c_str()); 1939 } 1940 nError++; 1941 } 1942 1943 RegistryKey subKey2; 1944 if ( key2.openKey(keyName, subKey2) ) 1945 { 1946 if ( options.forceOutput() ) 1947 { 1948 fprintf(stdout, "ERROR: could not open key \"%s\" in registry \"%s\"\n", 1949 U2S(*iter), options.getRegName2().c_str()); 1950 } 1951 nError++; 1952 } 1953 1954 if ( subKey1.isValid() && subKey2.isValid() ) 1955 { 1956 nError += compareKeys(options, subKey1, subKey2); 1957 } 1958 ++iter; 1959 } 1960 1961 return nError; 1962 } 1963 1964 #if (defined UNX) || (defined OS2) || defined __MINGW32__ 1965 int main( int argc, char * argv[] ) 1966 #else 1967 int _cdecl main( int argc, char * argv[] ) 1968 #endif 1969 { 1970 std::vector< std::string > args; 1971 1972 Options_Impl options(argv[0]); 1973 for (int i = 1; i < argc; i++) 1974 { 1975 if (!Options::checkArgument(args, argv[i], strlen(argv[i]))) 1976 { 1977 // failure. 1978 options.printUsage(); 1979 return (1); 1980 } 1981 } 1982 if (!options.initOptions(args)) 1983 { 1984 return (1); 1985 } 1986 1987 OUString regName1( convertToFileUrl(options.getRegName1().c_str(), options.getRegName1().size()) ); 1988 OUString regName2( convertToFileUrl(options.getRegName2().c_str(), options.getRegName2().size()) ); 1989 1990 Registry reg1, reg2; 1991 if ( reg1.open(regName1, REG_READONLY) ) 1992 { 1993 fprintf(stdout, "%s: open registry \"%s\" failed\n", 1994 options.getProgramName().c_str(), options.getRegName1().c_str()); 1995 return (2); 1996 } 1997 if ( reg2.open(regName2, REG_READONLY) ) 1998 { 1999 fprintf(stdout, "%s: open registry \"%s\" failed\n", 2000 options.getProgramName().c_str(), options.getRegName2().c_str()); 2001 return (3); 2002 } 2003 2004 RegistryKey key1, key2; 2005 if ( reg1.openRootKey(key1) ) 2006 { 2007 fprintf(stdout, "%s: open root key of registry \"%s\" failed\n", 2008 options.getProgramName().c_str(), options.getRegName1().c_str()); 2009 return (4); 2010 } 2011 if ( reg2.openRootKey(key2) ) 2012 { 2013 fprintf(stdout, "%s: open root key of registry \"%s\" failed\n", 2014 options.getProgramName().c_str(), options.getRegName2().c_str()); 2015 return (5); 2016 } 2017 2018 if ( options.isStartKeyValid() ) 2019 { 2020 if ( options.matchedWithExcludeKey( options.getStartKey() ) ) 2021 { 2022 fprintf(stdout, "%s: start key is equal to one of the exclude keys\n", 2023 options.getProgramName().c_str()); 2024 return (6); 2025 } 2026 RegistryKey sk1, sk2; 2027 if ( key1.openKey(options.getStartKey(), sk1) ) 2028 { 2029 fprintf(stdout, "%s: open start key of registry \"%s\" failed\n", 2030 options.getProgramName().c_str(), options.getRegName1().c_str()); 2031 return (7); 2032 } 2033 if ( key2.openKey(options.getStartKey(), sk2) ) 2034 { 2035 fprintf(stdout, "%s: open start key of registry \"%s\" failed\n", 2036 options.getProgramName().c_str(), options.getRegName2().c_str()); 2037 return (8); 2038 } 2039 2040 key1 = sk1; 2041 key2 = sk2; 2042 } 2043 2044 sal_uInt32 nError = compareKeys(options, key1, key2); 2045 if ( nError ) 2046 { 2047 if ( options.unoTypeCheck() ) 2048 { 2049 fprintf(stdout, "%s: registries are incompatible: %lu differences!\n", 2050 options.getProgramName().c_str(), 2051 sal::static_int_cast< unsigned long >(nError)); 2052 } 2053 else 2054 { 2055 fprintf(stdout, "%s: registries contain %lu differences!\n", 2056 options.getProgramName().c_str(), 2057 sal::static_int_cast< unsigned long >(nError)); 2058 } 2059 } 2060 else 2061 { 2062 if ( options.unoTypeCheck() ) 2063 { 2064 fprintf(stdout, "%s: registries are compatible!\n", 2065 options.getProgramName().c_str()); 2066 } 2067 else 2068 { 2069 fprintf(stdout, "%s: registries are equal!\n", 2070 options.getProgramName().c_str()); 2071 } 2072 } 2073 2074 key1.releaseKey(); 2075 key2.releaseKey(); 2076 if ( reg1.close() ) 2077 { 2078 fprintf(stdout, "%s: closing registry \"%s\" failed\n", 2079 options.getProgramName().c_str(), options.getRegName1().c_str()); 2080 return (9); 2081 } 2082 if ( reg2.close() ) 2083 { 2084 fprintf(stdout, "%s: closing registry \"%s\" failed\n", 2085 options.getProgramName().c_str(), options.getRegName2().c_str()); 2086 return (10); 2087 } 2088 2089 return ((nError > 0) ? 11 : 0); 2090 } 2091