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