/************************************************************************* * * $RCSfile: regcompare.cxx,v $ * * $Revision: 1.18 $ * * last change: $Author: obo $ $Date: 2004-06-04 02:46:32 $ * * The Contents of this file are made available subject to the terms of * either of the following licenses * * - GNU Lesser General Public License Version 2.1 * - Sun Industry Standards Source License Version 1.1 * * Sun Microsystems Inc., October, 2000 * * GNU Lesser General Public License Version 2.1 * ============================================= * Copyright 2000 by Sun Microsystems, Inc. * 901 San Antonio Road, Palo Alto, CA 94303, USA * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License version 2.1, as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA * * * Sun Industry Standards Source License Version 1.1 * ================================================= * The contents of this file are subject to the Sun Industry Standards * Source License Version 1.1 (the "License"); You may not use this file * except in compliance with the License. You may obtain a copy of the * License at http://www.openoffice.org/license.html. * * Software provided under this License is provided on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. * See the License for the specific provisions governing your rights and * obligations concerning the Software. * * The Initial Developer of the Original Code is: Sun Microsystems, Inc. * * Copyright: 2000 by Sun Microsystems, Inc. * * All Rights Reserved. * * Contributor(s): _______________________________________ * * ************************************************************************/ #include #include #include #include #ifndef _REGISTRY_REGISTRY_HXX_ #include "registry/registry.hxx" #endif #include "registry/reader.hxx" #include "registry/version.h" #ifndef _RTL_USTRING_HXX_ #include #endif #ifndef _RTL_ALLOC_H_ #include #endif #ifndef _OSL_PROCESS_H_ #include #endif #ifndef _OSL_DIAGNOSE_H_ #include #endif #ifndef _OSL_THREAD_H_ #include #endif #ifndef _OSL_FILE_HXX_ #include #endif #ifdef SAL_UNX #define SEPARATOR '/' #else #define SEPARATOR '\\' #endif using namespace ::rtl; using namespace ::osl; OUString shortName(const OUString& fullName) { return fullName.copy(fullName.lastIndexOf('/') + 1); } sal_Bool isFileUrl(const OString& fileName) { if (fileName.indexOf("file://") == 0 ) return sal_True; return sal_False; } OUString convertToFileUrl(const OString& fileName) { if ( isFileUrl(fileName) ) { return OStringToOUString(fileName, osl_getThreadTextEncoding()); } OUString uUrlFileName; OUString uFileName(fileName.getStr(), fileName.getLength(), osl_getThreadTextEncoding()); if ( fileName.indexOf('.') == 0 || fileName.indexOf(SEPARATOR) < 0 ) { OUString uWorkingDir; OSL_VERIFY( osl_getProcessWorkingDir(&uWorkingDir.pData) == osl_Process_E_None ); OSL_VERIFY( FileBase::getAbsoluteFileURL(uWorkingDir, uFileName, uUrlFileName) == FileBase::E_None ); } else { OSL_VERIFY( FileBase::getFileURLFromSystemPath(uFileName, uUrlFileName) == FileBase::E_None ); } return uUrlFileName; } #define U2S( s ) \ OUStringToOString(s, RTL_TEXTENCODING_UTF8).getStr() #define S2U( s ) \ OStringToOUString(s, RTL_TEXTENCODING_UTF8) struct LessString { sal_Bool operator()(const OUString& str1, const OUString& str2) const { return (str1 < str2); } }; typedef ::std::set< OUString, LessString > StringSet; class Options { public: Options() : m_bFullCheck(sal_False) , m_bForceOutput(sal_False) , m_bUnoTypeCheck(sal_False) , m_checkUnpublished(false) {} ~Options() {} sal_Bool initOptions(int ac, char* av[], sal_Bool bCmdFile=sal_False); OString prepareHelp(); OString prepareVersion(); const OString& getProgramName() { return m_program; } const OString& getRegName1() { return m_regName1; } const OString& getRegName2() { return m_regName2; } sal_Bool isStartKeyValid() { return (m_startKey.getLength() > 0); }; const OString& getStartKey() { return m_startKey; } sal_Bool existsExcludeKeys() { return !m_excludeKeys.empty(); }; StringSet& getExcludeKeys() { return m_excludeKeys; } sal_Bool matchedWithExcludeKey( const OUString& keyName); sal_Bool fullCheck() { return m_bFullCheck; } sal_Bool forceOutput() { return m_bForceOutput; } sal_Bool unoTypeCheck() { return m_bUnoTypeCheck; } bool checkUnpublished() const { return m_checkUnpublished; } protected: OString m_program; OString m_regName1; OString m_regName2; OString m_startKey; StringSet m_excludeKeys; sal_Bool m_bFullCheck; sal_Bool m_bForceOutput; sal_Bool m_bUnoTypeCheck; bool m_checkUnpublished; }; sal_Bool Options::initOptions(int ac, char* av[], sal_Bool bCmdFile) { sal_Bool bRet = sal_True; sal_uInt16 i=0; if (!bCmdFile) { bCmdFile = sal_True; m_program = av[0]; if (ac < 2) { fprintf(stdout, "%s", prepareHelp().getStr()); bRet = sal_False; } i = 1; } else { i = 0; } char *s=NULL; for (i; i < ac; i++) { if (av[i][0] == '-') { switch (av[i][1]) { case 'r': case 'R': { sal_Bool bFirst = sal_True; if (av[i][2] == '2') { bFirst = sal_False; } else if (av[i][2] != '1') { fprintf(stdout, "%s: invalid option '%s'\n", m_program.getStr(), av[i]); } if (av[i][3] == '\0') { if (i < ac - 1 && av[i+1][0] != '-') { i++; s = av[i]; } else { fprintf(stdout, "%s: invalid option '%s'\n", m_program.getStr(), av[i]); bRet = sal_False; break; } } else { s = av[i] + 2; } if ( bFirst ) { m_regName1 = OString(s); } else { m_regName2 = OString(s); } } break; case 's': case 'S': if (av[i][2] == '\0') { if (i < ac - 1 && av[i+1][0] != '-') { i++; s = av[i]; } else { fprintf(stdout, "%s: invalid option '%s'\n", m_program.getStr(), av[i]); bRet = sal_False; break; } } else { s = av[i] + 2; } m_startKey = OString(s); break; case 'x': case 'X': if (av[i][2] == '\0') { if (i < ac - 1 && av[i+1][0] != '-') { i++; s = av[i]; } else { fprintf(stdout, "%s: invalid option '%s'\n", m_program.getStr(), av[i]); bRet = sal_False; break; } } else { s = av[i] + 2; } m_excludeKeys.insert(S2U(s)); break; case 'c': case 'C': if (av[i][2] != '\0') { fprintf(stdout, "%s: invalid option '%s'\n", m_program.getStr(), av[i]); } m_bFullCheck = sal_True; break; case 'f': case 'F': if (av[i][2] != '\0') { fprintf(stdout, "%s: invalid option '%s'\n", m_program.getStr(), av[i]); bRet = sal_False; } m_bForceOutput = sal_True; break; case 't': case 'T': if (av[i][2] != '\0') { fprintf(stdout, "%s: invalid option '%s'\n", m_program.getStr(), av[i]); } m_bUnoTypeCheck = sal_True; break; case 'u': case 'U': if (av[i][2] != '\0') { fprintf(stdout, "%s: invalid option '%s'\n", m_program.getStr(), av[i]); } m_checkUnpublished = true; break; case 'h': case '?': if (av[i][2] != '\0') { fprintf(stdout, "%s: invalid option '%s'\n", m_program.getStr(), av[i]); bRet = sal_False; } else { fprintf(stdout, "%s", prepareHelp().getStr()); exit(0); } break; default: fprintf(stdout, "%s: unknown option '%s'\n", m_program.getStr(), av[i]); bRet = sal_False; break; } } else { if (av[i][0] == '@') { FILE* cmdFile = fopen(av[i]+1, "r"); if( cmdFile == NULL ) { fprintf(stdout, "%s", prepareHelp().getStr()); bRet = sal_False; } else { int rargc=0; char* rargv[512]; char buffer[512]; while ( fscanf(cmdFile, "%s", buffer) != EOF ) { rargv[rargc]= strdup(buffer); rargc++; } fclose(cmdFile); bRet = initOptions(rargc, rargv, bCmdFile); for (long i=0; i < rargc; i++) { free(rargv[i]); } } } else { fprintf(stdout, "%s: unknown option '%s'\n", m_program.getStr(), av[i]); bRet = sal_False; } } } if ( bRet ) { if ( m_regName1.getLength() == 0 ) { fprintf(stdout, "%s: missing option '-r1'\n", m_program.getStr()); bRet = sal_False; } if ( m_regName2.getLength() == 0 ) { fprintf(stdout, "%s: missing option '-r2'\n", m_program.getStr()); bRet = sal_False; } } return bRet; } OString Options::prepareHelp() { OString help("\nusing: "); help += m_program + " -r1 -r2 [-options] | @\n"; help += " -r1 = filename specifies the name of the first registry.\n"; help += " -r2 = filename specifies the name of the second registry.\n"; help += " @ = filename specifies a command file.\n"; help += "Options:\n"; help += " -s = name specifies the name of a start key. If no start key\n"; help += " |S is specified the comparison starts with the root key.\n"; help += " -x = name specifies the name of a key which won't be compared. All\n"; help += " |X subkeys won't be compared also. This option can be used more than once.\n"; help += " -f|F = force the detailed output of any diffenrences. Default\n"; help += " is that only the number of differences is returned.\n"; help += " -c|C = make a complete check, that means any differences will be\n"; help += " detected. Default is only a compatibility check that means\n"; help += " only UNO typelibrary entries will be checked.\n"; help += " -t|T = make an UNO type compatiblity check. This means that registry 2\n"; help += " will be checked against registry 1. If a interface in r2 contains\n"; help += " more methods or the methods are in a different order as in r1, r2 is\n"; help += " incompatible to r1. But if a service in r2 supports more properties as\n"; help += " in r1 and the new properties are 'optonal' it is compatible.\n"; help += " -u|U = additionally check types that are unpublished in registry 1.\n"; help += " -h|-? = print this help message and exit.\n"; help += prepareVersion(); return help; } OString Options::prepareVersion() { OString version("\nSun Microsystems (R) "); version += m_program + " Version 1.0\n\n"; return version; } sal_Bool Options::matchedWithExcludeKey( const OUString& keyName) { if ( m_excludeKeys.empty() ) return sal_False; StringSet::const_iterator iter = m_excludeKeys.begin(); StringSet::const_iterator end = m_excludeKeys.end(); while ( iter != end ) { if ( keyName.indexOf(*iter) == 0) return sal_True; ++iter; } return sal_False; } static Options options; static sal_Char* getTypeClass(RTTypeClass typeClass) { switch (typeClass) { case RT_TYPE_INTERFACE: return "INTERFACE"; case RT_TYPE_MODULE: return "MODULE"; case RT_TYPE_STRUCT: return "STRUCT"; case RT_TYPE_ENUM: return "ENUM"; case RT_TYPE_EXCEPTION: return "EXCEPTION"; case RT_TYPE_TYPEDEF: return "TYPEDEF"; case RT_TYPE_SERVICE: return "SERVICE"; case RT_TYPE_OBJECT: return "OBJECT"; case RT_TYPE_CONSTANTS: return "CONSTANTS"; } return "INVALID"; } static OString getFieldAccess(RTFieldAccess fieldAccess) { OString ret; if ( (fieldAccess & RT_ACCESS_INVALID) == RT_ACCESS_INVALID ) { ret += OString("INVALID"); } if ( (fieldAccess & RT_ACCESS_READONLY) == RT_ACCESS_READONLY ) { ret += OString(ret.getLength() > 0 ? ",READONLY" : "READONLY"); } if ( (fieldAccess & RT_ACCESS_OPTIONAL) == RT_ACCESS_OPTIONAL ) { ret += OString(ret.getLength() > 0 ? ",OPTIONAL" : "OPTIONAL"); } if ( (fieldAccess & RT_ACCESS_MAYBEVOID) == RT_ACCESS_MAYBEVOID ) { ret += OString(ret.getLength() > 0 ? ",MAYBEVOID" : "MAYBEVOID"); } if ( (fieldAccess & RT_ACCESS_BOUND) == RT_ACCESS_BOUND ) { ret += OString(ret.getLength() > 0 ? ",BOUND" : "BOUND"); } if ( (fieldAccess & RT_ACCESS_CONSTRAINED) == RT_ACCESS_CONSTRAINED ) { ret += OString(ret.getLength() > 0 ? ",CONSTRAINED" : "CONSTRAINED"); } if ( (fieldAccess & RT_ACCESS_TRANSIENT) == RT_ACCESS_TRANSIENT ) { ret += OString(ret.getLength() > 0 ? ",TRANSIENT" : "TRANSIENT"); } if ( (fieldAccess & RT_ACCESS_MAYBEAMBIGUOUS) == RT_ACCESS_MAYBEAMBIGUOUS ) { ret += OString(ret.getLength() > 0 ? ",MAYBEAMBIGUOUS" : "MAYBEAMBIGUOUS"); } if ( (fieldAccess & RT_ACCESS_MAYBEDEFAULT) == RT_ACCESS_MAYBEDEFAULT ) { ret += OString(ret.getLength() > 0 ? ",MAYBEDEFAULT" : "MAYBEDEFAULT"); } if ( (fieldAccess & RT_ACCESS_REMOVEABLE) == RT_ACCESS_REMOVEABLE ) { ret += OString(ret.getLength() > 0 ? ",REMOVEABLE" : "REMOVEABLE"); } if ( (fieldAccess & RT_ACCESS_ATTRIBUTE) == RT_ACCESS_ATTRIBUTE ) { ret += OString(ret.getLength() > 0 ? ",ATTRIBUTE" : "ATTRIBUTE"); } if ( (fieldAccess & RT_ACCESS_PROPERTY) == RT_ACCESS_PROPERTY ) { ret += OString(ret.getLength() > 0 ? ",PROPERTY" : "PROPERTY"); } if ( (fieldAccess & RT_ACCESS_CONST) == RT_ACCESS_CONST ) { ret += OString(ret.getLength() > 0 ? ",CONST" : "CONST"); } if ( (fieldAccess & RT_ACCESS_READWRITE) == RT_ACCESS_READWRITE ) { ret += OString(ret.getLength() > 0 ? ",READWRITE" : "READWRITE"); } return ret; } static sal_Char* getConstValueType(RTConstValue& constValue) { switch (constValue.m_type) { case RT_TYPE_BOOL: return "sal_Bool"; case RT_TYPE_BYTE: return "sal_uInt8"; case RT_TYPE_INT16: return "sal_Int16"; case RT_TYPE_UINT16: return "sal_uInt16"; case RT_TYPE_INT32: return "sal_Int32"; case RT_TYPE_UINT32: return "sal_uInt32"; // case RT_TYPE_INT64: // return "sal_Int64"; // case RT_TYPE_UINT64: // return "sal_uInt64"; case RT_TYPE_FLOAT: return "float"; case RT_TYPE_DOUBLE: return "double"; case RT_TYPE_STRING: return "sal_Unicode*"; } return "NONE"; } static void printConstValue(RTConstValue& constValue) { switch (constValue.m_type) { case RT_TYPE_NONE: fprintf(stdout, "none"); case RT_TYPE_BOOL: fprintf(stdout, "%s", constValue.m_value.aBool ? "TRUE" : "FALSE"); case RT_TYPE_BYTE: fprintf(stdout, "%d", constValue.m_value.aByte); case RT_TYPE_INT16: fprintf(stdout, "%d", constValue.m_value.aShort); case RT_TYPE_UINT16: fprintf(stdout, "%d", constValue.m_value.aUShort); case RT_TYPE_INT32: fprintf(stdout, "%d", constValue.m_value.aLong); case RT_TYPE_UINT32: fprintf(stdout, "%d", constValue.m_value.aULong); // case RT_TYPE_INT64: // fprintf(stdout, "%d", constValue.m_value.aHyper); // case RT_TYPE_UINT64: // fprintf(stdout, "%d", constValue.m_value.aUHyper); case RT_TYPE_FLOAT: fprintf(stdout, "%f", constValue.m_value.aFloat); case RT_TYPE_DOUBLE: fprintf(stdout, "%f", constValue.m_value.aDouble); case RT_TYPE_STRING: fprintf(stdout, "%s", constValue.m_value.aString); } } static sal_uInt32 checkConstValue(const OUString& keyName, RTTypeClass typeClass, sal_Bool& bDump, RTConstValue& constValue1, RTConstValue& constValue2, sal_uInt16 index1, sal_uInt16 index2) { switch (constValue1.m_type) { case RT_TYPE_BOOL: if (constValue1.m_value.aBool != constValue2.m_value.aBool) { if ( options.forceOutput() && !options.unoTypeCheck() ) { if ( bDump ) { fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName)); bDump = sal_False; } fprintf(stdout, " Field %d: Value1 = %s != Value2 = %s\n", index1, constValue1.m_value.aBool ? "TRUE" : "FALSE", constValue2.m_value.aBool ? "TRUE" : "FALSE"); } return 1; } break; case RT_TYPE_BYTE: if (constValue1.m_value.aByte != constValue2.m_value.aByte) { if ( options.forceOutput() && !options.unoTypeCheck() ) { if ( bDump ) { fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName)); bDump = sal_False; } fprintf(stdout, " Field %d: Value1 = %d != Value2 = %d\n", index1, constValue1.m_value.aByte, constValue2.m_value.aByte); } return 1; } break; case RT_TYPE_INT16: if (constValue1.m_value.aShort != constValue2.m_value.aShort) { if ( options.forceOutput() && !options.unoTypeCheck() ) { if ( bDump ) { fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName)); bDump = sal_False; } fprintf(stdout, " Field %d: Value1 = %d != Value2 = %d\n", index1, constValue1.m_value.aShort, constValue2.m_value.aShort); } return 1; } break; case RT_TYPE_UINT16: if (constValue1.m_value.aUShort != constValue2.m_value.aUShort) { if ( options.forceOutput() && !options.unoTypeCheck() ) { if ( bDump ) { fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName)); bDump = sal_False; } fprintf(stdout, " Field %d: Value1 = %d != Value2 = %d\n", index1, constValue1.m_value.aUShort, constValue2.m_value.aUShort); } return 1; } break; case RT_TYPE_INT32: if (constValue1.m_value.aLong != constValue2.m_value.aLong) { if ( options.forceOutput() && !options.unoTypeCheck() ) { if ( bDump ) { fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName)); bDump = sal_False; } fprintf(stdout, " Field %d: Value1 = %d != Value2 = %d\n", index1, constValue1.m_value.aLong, constValue2.m_value.aLong); } return 1; } break; case RT_TYPE_UINT32: if (constValue1.m_value.aULong != constValue2.m_value.aULong) { if ( options.forceOutput() && !options.unoTypeCheck() ) { if ( bDump ) { fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName)); bDump = sal_False; } fprintf(stdout, " Field %d: Value1 = %d != Value2 = %d\n", index1, constValue1.m_value.aULong, constValue2.m_value.aULong); } return 1; } break; // case RT_TYPE_INT64: // if (constValue1.m_value.aHyper != constValue2.m_value.aHyper) // { // if ( options.forceOutput() && !options.unoTypeCheck() ) // { // if ( bDump ) // { // fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName)); // bDump = sal_False; // } // fprintf(stdout, " Field %d: Value1 = %d != Value2 = %d\n", index1, // constValue1.m_value.aHyper, constValue2.m_value.aHyper); // } // return 1; // } // break; // case RT_TYPE_UINT64: // if (constValue1.m_value.aUHyper != constValue2.m_value.aUHyper) // { // if ( options.forceOutput() && !options.unoTypeCheck() ) // { // if ( bDump ) // { // fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName)); // bDump = sal_False; // } // fprintf(stdout, " Field %d: Value1 = %d != Value2 = %d\n", index1, // constValue1.m_value.aUHyper, constValue2.m_value.aUHyper); // } // return 1; // } // break; case RT_TYPE_FLOAT: if (constValue1.m_value.aFloat != constValue2.m_value.aFloat) { if ( options.forceOutput() && !options.unoTypeCheck() ) { if ( bDump ) { fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName)); bDump = sal_False; } fprintf(stdout, " Field %d: Value1 = %d != Value2 = %d\n", index1, constValue1.m_value.aFloat, constValue2.m_value.aFloat); } return 1; } break; case RT_TYPE_DOUBLE: if (constValue1.m_value.aDouble != constValue2.m_value.aDouble) { if ( options.forceOutput() && !options.unoTypeCheck() ) { if ( bDump ) { fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName)); bDump = sal_False; } fprintf(stdout, " Field %d: Value1 = %d != Value2 = %d\n", index1, constValue1.m_value.aDouble, constValue2.m_value.aDouble); } return 1; } break; case RT_TYPE_STRING: if (rtl_ustr_compare(constValue1.m_value.aString, constValue2.m_value.aString) != 0) { if ( options.forceOutput() && !options.unoTypeCheck() ) { if ( bDump ) { fprintf(stdout, "%s\n", U2S(keyName)); fprintf(stdout, " TypeClass = %s\n", getTypeClass(typeClass)); bDump = sal_False; } fprintf(stdout, " Field %d: Value1 = %d != Value2 = %d\n", index1, constValue1.m_value.aString, constValue2.m_value.aString); } return 1; } } return 0; } static sal_uInt32 checkField(const OUString& keyName, RTTypeClass typeClass, sal_Bool& bDump, typereg::Reader& reader1, typereg::Reader& reader2, sal_uInt16 index1, sal_uInt16 index2) { sal_uInt32 nError = 0; if ( reader1.getFieldName(index1) != reader2.getFieldName(index2) ) { if ( options.forceOutput() && !options.unoTypeCheck() ) { if ( bDump ) { fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName)); bDump = sal_False; } fprintf(stdout, " Field %d: Name1 = %s != Name2 = %s\n", index1, U2S(reader1.getFieldName(index1)), U2S(reader2.getFieldName(index2))); } nError++; } if ( reader1.getFieldTypeName(index1) != reader2.getFieldTypeName(index2) ) { if ( options.forceOutput() && !options.unoTypeCheck() ) { if ( bDump ) { fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName)); bDump = sal_False; } fprintf(stdout, " Field %d: Type1 = %s != Type2 = %s\n", index1, U2S(reader1.getFieldTypeName(index1)), U2S(reader2.getFieldTypeName(index2))); } nError++; } else { RTConstValue constValue1 = reader1.getFieldValue(index1); RTConstValue constValue2 = reader2.getFieldValue(index2); if ( constValue1.m_type != constValue2.m_type ) { if ( options.forceOutput() && !options.unoTypeCheck() ) { if ( bDump ) { fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName)); bDump = sal_False; } fprintf(stdout, " Field %d: Access1 = %s != Access2 = %s\n", index1, getConstValueType(constValue1), getConstValueType(constValue2)); fprintf(stdout, " Field %d: Value1 = ", index1); printConstValue(constValue1); fprintf(stdout, " != Value2 = "); printConstValue(constValue1); fprintf(stdout, "\n;"); } nError++; } else { nError += checkConstValue(keyName, typeClass, bDump, constValue1, constValue2, index1, index2); } } if ( reader1.getFieldFlags(index1) != reader2.getFieldFlags(index2) ) { if ( options.forceOutput() && !options.unoTypeCheck() ) { if ( bDump ) { fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName)); bDump = sal_False; } fprintf(stdout, " Field %d: FieldAccess1 = %s != FieldAccess2 = %s\n", index1, getFieldAccess(reader1.getFieldFlags(index1)).getStr(), getFieldAccess(reader1.getFieldFlags(index2)).getStr()); } nError++; } if ( options.fullCheck() && (reader1.getFieldDocumentation(index1) != reader2.getFieldDocumentation(index2)) ) { if ( options.forceOutput() && !options.unoTypeCheck() ) { if ( bDump ) { fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName)); bDump = sal_False; } fprintf(stdout, " Field %d: Doku1 = %s\n Doku2 = %s\n", index1, U2S(reader1.getFieldDocumentation(index1)), U2S(reader2.getFieldDocumentation(index2))); } nError++; } if ( options.fullCheck() && (reader1.getFieldFileName(index1) != reader2.getFieldFileName(index2)) ) { if ( options.forceOutput() && !options.unoTypeCheck() ) { if ( bDump ) { fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName)); bDump = sal_False; } fprintf(stdout, " Field %d: FileName1 = %s != FileName2 = %s\n", index1, U2S(reader1.getFieldFileName(index1)), U2S(reader2.getFieldFileName(index2))); } nError++; } return nError; } static sal_Char* getMethodMode(RTMethodMode methodMode) { switch ( methodMode ) { case RT_MODE_ONEWAY: return "ONEWAY"; case RT_MODE_ONEWAY_CONST: return "ONEWAY,CONST"; case RT_MODE_TWOWAY: return "NONE"; case RT_MODE_TWOWAY_CONST: return "CONST"; } return "INVALID"; } static sal_Char* getParamMode(RTParamMode paramMode) { switch ( paramMode ) { case RT_PARAM_IN: return "IN"; case RT_PARAM_OUT: return "OUT"; case RT_PARAM_INOUT: return "INOUT"; } return "INVALID"; } static sal_uInt32 checkMethod(const OUString& keyName, RTTypeClass typeClass, sal_Bool& bDump, typereg::Reader& reader1, typereg::Reader& reader2, sal_uInt16 index) { sal_uInt32 nError = 0; if ( reader1.getMethodName(index) != reader2.getMethodName(index) ) { if ( options.forceOutput() ) { if ( bDump ) { fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName)); bDump = sal_False; } fprintf(stdout, " Method1 %d: Name1 = %s != Name2 = %s\n", index, U2S(reader1.getMethodName(index)), U2S(reader2.getMethodName(index))); } nError++; } if ( reader1.getMethodReturnTypeName(index) != reader2.getMethodReturnTypeName(index) ) { if ( options.forceOutput() ) { if ( bDump ) { fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName)); bDump = sal_False; } fprintf(stdout, " Method1 %d: ReturnType1 = %s != ReturnType2 = %s\n", index, U2S(reader1.getMethodReturnTypeName(index)), U2S(reader2.getMethodReturnTypeName(index))); } nError++; } sal_uInt16 nParams1 = (sal_uInt16)reader1.getMethodParameterCount(index); sal_uInt16 nParams2 = (sal_uInt16)reader2.getMethodParameterCount(index); if ( nParams1 != nParams2 ) { if ( options.forceOutput() ) { if ( bDump ) { fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName)); bDump = sal_False; } fprintf(stdout, " Method %d : nParameters1 = %d != nParameters2 = %d\n", index, nParams1, nParams2); } nError++; } sal_uInt16 i=0; for (i=0; i < nParams1 && i < nParams2; i++) { if ( reader1.getMethodParameterTypeName(index, i) != reader2.getMethodParameterTypeName(index, i) ) { if ( options.forceOutput() ) { if ( bDump ) { fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName)); bDump = sal_False; } fprintf(stdout, " Method %d, Parameter %d: Type1 = %s != Type2 = %s\n", index, i, U2S(reader1.getMethodParameterTypeName(index, i)), U2S(reader2.getMethodParameterTypeName(index, i))); } nError++; } if ( options.fullCheck() && (reader1.getMethodParameterName(index, i) != reader2.getMethodParameterName(index, i)) ) { if ( options.forceOutput() ) { if ( bDump ) { fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName)); bDump = sal_False; } fprintf(stdout, " Method %d, Parameter %d: Name1 = %s != Name2 = %s\n", index, i, U2S(reader1.getMethodParameterName(index, i)), U2S(reader2.getMethodParameterName(index, i))); } nError++; } if ( reader1.getMethodParameterFlags(index, i) != reader2.getMethodParameterFlags(index, i) ) { if ( options.forceOutput() ) { if ( bDump ) { fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName)); bDump = sal_False; } fprintf(stdout, " Method %d, Parameter %d: Mode1 = %s != Mode2 = %s\n", index, i, getParamMode(reader1.getMethodParameterFlags(index, i)), getParamMode(reader2.getMethodParameterFlags(index, i))); } nError++; } } if ( i < nParams1 && options.forceOutput() ) { if ( bDump ) { fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName)); bDump = sal_False; } fprintf(stdout, " Registry1: Method %d contains %d more parameters\n", index, nParams1 - i); } if ( i < nParams2 && options.forceOutput() ) { if ( bDump ) { fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName)); bDump = sal_False; } fprintf(stdout, " Registry2: Method %d contains %d more parameters\n", index, nParams2 - i); } sal_uInt16 nExcep1 = (sal_uInt16)reader1.getMethodExceptionCount(index); sal_uInt16 nExcep2 = (sal_uInt16)reader2.getMethodExceptionCount(index); if ( nExcep1 != nExcep2 ) { if ( options.forceOutput() ) { if ( bDump ) { fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName)); bDump = sal_False; } fprintf(stdout, " nExceptions1 = %d != nExceptions2 = %d\n", nExcep1, nExcep2); } nError++; } for (i=0; i < nExcep1 && i < nExcep2; i++) { if ( reader1.getMethodExceptionTypeName(index, i) != reader2.getMethodExceptionTypeName(index, i) ) { if ( options.forceOutput() ) { if ( bDump ) { fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName)); bDump = sal_False; } fprintf(stdout, " Method %d, Exception %d: Name1 = %s != Name2 = %s\n", index, i, U2S(reader1.getMethodExceptionTypeName(index, i)), U2S(reader2.getMethodExceptionTypeName(index, i))); } nError++; } } if ( i < nExcep1 && options.forceOutput() ) { if ( bDump ) { fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName)); bDump = sal_False; } fprintf(stdout, " Registry1: Method %d contains %d more exceptions\n", index, nExcep1 - i); } if ( i < nExcep2 && options.forceOutput() ) { if ( bDump ) { fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName)); bDump = sal_False; } fprintf(stdout, " Registry2: Method %d contains %d more exceptions\n", index, nExcep2 - i); } if ( reader1.getMethodFlags(index) != reader2.getMethodFlags(index) ) { if ( options.forceOutput() ) { if ( bDump ) { fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName)); bDump = sal_False; } fprintf(stdout, " Method %d: Mode1 = %s != Mode2 = %s\n", index, getMethodMode(reader1.getMethodFlags(index)), getMethodMode(reader2.getMethodFlags(index))); } nError++; } if ( options.fullCheck() && (reader1.getMethodDocumentation(index) != reader2.getMethodDocumentation(index)) ) { if ( options.forceOutput() ) { if ( bDump ) { fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName)); bDump = sal_False; } fprintf(stdout, " Method %d: Doku1 = %s\n Doku2 = %s\n", index, U2S(reader1.getMethodDocumentation(index)), U2S(reader2.getMethodDocumentation(index))); } nError++; } return nError; } static sal_Char* getReferenceType(RTReferenceType refType) { switch (refType) { case RT_REF_SUPPORTS: return "RT_REF_SUPPORTS"; case RT_REF_OBSERVES: return "RT_REF_OBSERVES"; case RT_REF_EXPORTS: return "RT_REF_EXPORTS"; case RT_REF_NEEDS: return "RT_REF_NEEDS"; } return "RT_REF_INVALID"; } static sal_uInt32 checkReference(const OUString& keyName, RTTypeClass typeClass, sal_Bool& bDump, typereg::Reader& reader1, typereg::Reader& reader2, sal_uInt16 index1, sal_uInt16 index2) { sal_uInt32 nError = 0; if ( reader1.getReferenceTypeName(index1) != reader2.getReferenceTypeName(index2) ) { if ( options.forceOutput() && !options.unoTypeCheck() ) { if ( bDump ) { fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName)); bDump = sal_False; } fprintf(stdout, " Reference %d: Name1 = %s != Name2 = %s\n", index1, U2S(reader1.getReferenceTypeName(index1)), U2S(reader2.getReferenceTypeName(index2))); } nError++; } if ( reader1.getReferenceTypeName(index1) != reader2.getReferenceTypeName(index2) ) { if ( options.forceOutput() && !options.unoTypeCheck() ) { if ( bDump ) { fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName)); bDump = sal_False; } fprintf(stdout, " Reference %d: Type1 = %s != Type2 = %s\n", index1, getReferenceType(reader1.getReferenceSort(index1)), getReferenceType(reader2.getReferenceSort(index2))); } nError++; } if ( options.fullCheck() && (reader1.getReferenceDocumentation(index1) != reader2.getReferenceDocumentation(index2)) ) { if ( options.forceOutput() && !options.unoTypeCheck() ) { if ( bDump ) { fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName)); bDump = sal_False; } fprintf(stdout, " Reference %d: Doku1 = %s\n Doku2 = %s\n", index1, U2S(reader1.getReferenceDocumentation(index1)), U2S(reader2.getReferenceDocumentation(index2))); } nError++; } if ( reader1.getReferenceFlags(index1) != reader2.getReferenceFlags(index2) ) { if ( options.forceOutput() && !options.unoTypeCheck() ) { if ( bDump ) { fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName)); bDump = sal_False; } fprintf(stdout, " Reference %d: Access1 = %s != Access2 = %s\n", index1, getFieldAccess(reader1.getReferenceFlags(index1)).getStr(), getFieldAccess(reader1.getReferenceFlags(index2)).getStr()); } nError++; } return nError; } static sal_uInt32 checkFieldsWithoutOrder(const OUString& keyName, RTTypeClass typeClass, sal_Bool& bDump, typereg::Reader& reader1, typereg::Reader& reader2) { sal_uInt32 nError = 0; sal_uInt16 nFields1 = (sal_uInt16)reader1.getFieldCount(); sal_uInt16 nFields2 = (sal_uInt16)reader2.getFieldCount(); sal_uInt16 i=0, j=0; if ( nFields1 > nFields2 ) { if ( options.forceOutput() ) { if ( bDump ) { fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName)); bDump = sal_False; } fprintf(stdout, " %s1 contains %d more properties as %s2\n", getTypeClass(typeClass), nFields1-nFields2, getTypeClass(typeClass)); } } sal_Bool bFound = sal_False; ::std::set< sal_uInt16, ::std::less< sal_uInt16 > > moreProps; for (i=0; i < nFields1; i++) { for (j=0; j < nFields2; j++) { if (!checkField(keyName, typeClass, bDump, reader1, reader2, i, j)) { bFound = sal_True; moreProps.insert(j); break; } } if (!bFound) { if (options.forceOutput()) { if ( bDump ) { fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName)); bDump = sal_False; } fprintf(stdout, " incompatible change: Field %d ('%s') of r1 is not longer a property of this %s in r2\n", i, U2S(shortName(reader1.getFieldName(i))), getTypeClass(typeClass)); } nError++; } else { bFound = sal_False; } } if ( typeClass == RT_TYPE_SERVICE && !moreProps.empty() ) { for (j=0; j < nFields2; j++) { if ( moreProps.find(j) == moreProps.end() ) { if ( (reader2.getFieldFlags(j) & RT_ACCESS_OPTIONAL) != RT_ACCESS_OPTIONAL ) { if ( options.forceOutput() ) { if ( bDump ) { fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName)); bDump = sal_False; } fprintf(stdout, " incompatible change: Field %d ('%s') of r2 is a new property compared to this %s in r1 and is not 'optional'\n", j, U2S(shortName(reader2.getFieldName(j))), getTypeClass(typeClass)); } nError++; } } } } return nError; } static sal_uInt32 checkBlob(const OUString& keyName, typereg::Reader& reader1, sal_uInt32 size1, typereg::Reader& reader2, sal_uInt32 size2) { sal_uInt32 nError = 0; sal_Bool bDump = sal_True; if ( options.fullCheck() && (size1 != size2) ) { if ( options.forceOutput() ) { fprintf(stdout, " Size1 = %d Size2 = %d\n", size1, size2); } } if (reader1.isPublished()) { if (!reader2.isPublished()) { if (options.forceOutput()) { if (bDump) { fprintf(stdout, "?: %s\n", U2S(keyName)); bDump = false; } fprintf(stdout, " published in 1 but unpublished in 2\n"); } ++nError; } } else if (!options.checkUnpublished()) { return nError; } if ( reader1.getTypeClass() != reader2.getTypeClass() ) { if ( options.forceOutput() ) { if (bDump) { fprintf(stdout, "?: %s\n", U2S(keyName)); bDump = sal_False; } fprintf(stdout, " TypeClass1 = %s != TypeClass2 = %s\n", getTypeClass(reader1.getTypeClass()), getTypeClass(reader2.getTypeClass())); } return ++nError; } RTTypeClass typeClass = reader1.getTypeClass(); if ( reader1.getTypeName() != reader2.getTypeName() ) { if ( options.forceOutput() ) { if ( bDump ) { fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName)); bDump = sal_False; } fprintf(stdout, " TypeName1 = %s != TypeName2 = %s\n", U2S(reader1.getTypeName()), U2S(reader2.getTypeName())); } nError++; } if ( (typeClass == RT_TYPE_INTERFACE || typeClass == RT_TYPE_STRUCT || typeClass == RT_TYPE_EXCEPTION) ) { if (reader1.getSuperTypeCount() != reader2.getSuperTypeCount()) { if (bDump) { fprintf( stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName)); bDump = false; } fprintf( stdout, " SuperTypeCount1 = %d != SuperTypeCount2 = %d\n", static_cast< int >(reader1.getSuperTypeCount()), static_cast< int >(reader2.getSuperTypeCount())); ++nError; } else { for (sal_Int16 i = 0; i < reader1.getSuperTypeCount(); ++i) { if (reader1.getSuperTypeName(i) != reader2.getSuperTypeName(i)) { if ( options.forceOutput() ) { if ( bDump ) { fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName)); bDump = sal_False; } fprintf(stdout, " SuperTypeName1 = %s != SuperTypeName2 = %s\n", U2S(reader1.getSuperTypeName(i)), U2S(reader2.getSuperTypeName(i))); } nError++; } } } } sal_uInt16 nFields1 = (sal_uInt16)reader1.getFieldCount(); sal_uInt16 nFields2 = (sal_uInt16)reader2.getFieldCount(); sal_uInt16 i=0; sal_Bool bCheckNormal = sal_True; if ( (typeClass == RT_TYPE_SERVICE || typeClass == RT_TYPE_MODULE || typeClass == RT_TYPE_CONSTANTS) && options.unoTypeCheck() ) { bCheckNormal = sal_False; } if ( bCheckNormal ) { if ( nFields1 != nFields2 ) { if ( options.forceOutput() ) { if ( bDump ) { fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName)); bDump = sal_False; } fprintf(stdout, " nFields1 = %d != nFields2 = %d\n", nFields1, nFields2); } nError++; } for (i=0; i < nFields1 && i < nFields2; i++) { nError += checkField(keyName, typeClass, bDump, reader1, reader2, i, i); } if ( i < nFields1 && options.forceOutput() ) { if ( bDump ) { fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName)); bDump = sal_False; } fprintf(stdout, " Registry1 contains %d more fields\n", nFields1 - i); } if ( i < nFields2 && options.forceOutput() ) { if ( bDump ) { fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName)); bDump = sal_False; } fprintf(stdout, " Registry2 contains %d more fields\n", nFields2 - i); } } else { nError += checkFieldsWithoutOrder(keyName, typeClass, bDump, reader1, reader2); } if ( typeClass == RT_TYPE_INTERFACE ) { sal_uInt16 nMethods1 = (sal_uInt16)reader1.getMethodCount(); sal_uInt16 nMethods2 = (sal_uInt16)reader2.getMethodCount(); if ( nMethods1 != nMethods2 ) { if ( options.forceOutput() ) { if ( bDump ) { fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName)); bDump = sal_False; } fprintf(stdout, " nMethods1 = %d != nMethods2 = %d\n", nMethods1, nMethods2); } nError++; } for (i=0; i < nMethods1 && i < nMethods2; i++) { nError += checkMethod(keyName, typeClass, bDump, reader1, reader2, i); } if ( i < nMethods1 && options.forceOutput() ) { fprintf(stdout, " Registry1 contains %d more methods\n", nMethods1 - i); } if ( i < nMethods2 && options.forceOutput() ) { fprintf(stdout, " Registry2 contains %d more methods\n", nMethods2 - i); } } if ( typeClass == RT_TYPE_SERVICE ) { sal_uInt16 nReference1 = (sal_uInt16)reader1.getReferenceCount(); sal_uInt16 nReference2 = (sal_uInt16)reader2.getReferenceCount(); if ( !bCheckNormal ) { sal_uInt16 i=0, j=0; if ( nReference1 > nReference2 ) { if ( options.forceOutput() ) { if ( bDump ) { fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName)); bDump = sal_False; } fprintf(stdout, " service1 contains %d more references as service2\n", nReference1-nReference2); } } sal_Bool bFound = sal_False; ::std::set< sal_uInt16, ::std::less< sal_uInt16 > > moreReferences; for (i=0; i < nReference1; i++) { for (j=0; j < nReference2; j++) { if (!checkReference(keyName, typeClass, bDump, reader1, reader2, i, j)) { bFound = sal_True; moreReferences.insert(j); break; } } if (!bFound) { if (options.forceOutput()) { if ( bDump ) { fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName)); bDump = sal_False; } fprintf(stdout, " incompatible change: Reference %d ('%s') in 'r1' is not longer a reference of this service in 'r2'\n", i, U2S(shortName(reader1.getReferenceTypeName(i)))); } nError++; } else { bFound = sal_False; } } if ( !moreReferences.empty() ) { for (j=0; j < nReference2; j++) { if ( moreReferences.find(j) == moreReferences.end() ) { if ( (reader2.getReferenceFlags(j) & RT_ACCESS_OPTIONAL) != RT_ACCESS_OPTIONAL ) { if ( options.forceOutput() ) { if ( bDump ) { fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName)); bDump = sal_False; } fprintf(stdout, " incompatible change: Reference %d ('%s') of r2 is a new reference compared to this service in r1 and is not 'optional'\n", j, U2S(shortName(reader2.getReferenceTypeName(j)))); } nError++; } } } } } else { if ( nReference1 != nReference2 ) { if ( options.forceOutput() ) { if ( bDump ) { fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName)); bDump = sal_False; } fprintf(stdout, " nReferences1 = %d != nReferences2 = %d\n", nReference1, nReference2); } nError++; } for (i=0; i < nReference1 && i < nReference2; i++) { nError += checkReference(keyName, typeClass, bDump, reader1, reader2, i, i); } if ( i < nReference1 && options.forceOutput() ) { fprintf(stdout, " Registry1 contains %d more references\n", nReference1 - i); } if ( i < nReference2 && options.forceOutput() ) { fprintf(stdout, " Registry2 contains %d more references\n", nReference2 - i); } } } if ( options.fullCheck() && (reader1.getDocumentation() != reader2.getDocumentation()) ) { if ( options.forceOutput() ) { if ( bDump ) { fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName)); bDump = sal_False; } fprintf(stdout, " Doku1 = %s\n Doku2 = %s\n", U2S(reader1.getDocumentation()), U2S(reader2.getDocumentation())); } nError++; } if ( options.fullCheck() && (reader1.getFileName() != reader2.getFileName()) ) { if ( options.forceOutput() ) { if ( bDump ) { fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName)); } fprintf(stdout, " FileName1 = %s != FileName2 = %s\n", U2S(reader1.getFileName()), U2S(reader2.getFileName())); } nError++; } /* if ( nError && (!keyName.compareTo(OUString::createFromAscii("/UCR/drafts"), 11) || !keyName.compareTo(OUString::createFromAscii("/drafts"), 7)) ) { if ( options.forceOutput() ) { if ( bDump ) { fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName)); bDump = sal_False; } fprintf(stdout, " Note: \"drafts\" type changed incompatible, no effect to the final API\n"); } return 0; } */ return nError; } static sal_uInt32 checkValueDifference(RegistryKey& key1, RegValueType valueType1, sal_uInt32 size1, RegistryKey& key2, RegValueType valueType2, sal_uInt32 size2) { OUString tmpName; sal_uInt32 nError = 0; if ( valueType1 == valueType2 ) { sal_Bool bEqual = sal_True; if ( valueType1 == RG_VALUETYPE_LONGLIST || valueType1 == RG_VALUETYPE_STRINGLIST || valueType1 == RG_VALUETYPE_UNICODELIST ) { switch (valueType1) { case RG_VALUETYPE_LONGLIST: { RegistryValueList valueList1; RegistryValueList valueList2; key1.getLongListValue(tmpName, valueList1); key2.getLongListValue(tmpName, valueList2); sal_uInt32 length1 = valueList1.getLength(); sal_uInt32 length2 = valueList1.getLength(); if ( length1 != length2 ) { bEqual = sal_False; break; } for (sal_uInt32 i=0; i valueList1; RegistryValueList valueList2; key1.getStringListValue(tmpName, valueList1); key2.getStringListValue(tmpName, valueList2); sal_uInt32 length1 = valueList1.getLength(); sal_uInt32 length2 = valueList1.getLength(); if ( length1 != length2 ) { bEqual = sal_False; break; } for (sal_uInt32 i=0; i valueList1; RegistryValueList valueList2; key1.getUnicodeListValue(tmpName, valueList1); key2.getUnicodeListValue(tmpName, valueList2); sal_uInt32 length1 = valueList1.getLength(); sal_uInt32 length2 = valueList1.getLength(); if ( length1 != length2 ) { bEqual = sal_False; break; } for (sal_uInt32 i=0; i valueList; key1.getLongListValue(tmpName, valueList); fprintf(stdout, " Registry 1: Value: Type = RG_VALUETYPE_LONGLIST\n"); fprintf(stdout, " Size = %d\n", size1); sal_uInt32 length = valueList.getLength(); for (sal_uInt32 i=0; i valueList; key1.getStringListValue(tmpName, valueList); fprintf(stdout, " Registry 1: Value: Type = RG_VALUETYPE_STRINGLIST\n"); fprintf(stdout, " Size = %d\n", size1); sal_uInt32 length = valueList.getLength(); for (sal_uInt32 i=0; i valueList; key1.getUnicodeListValue(tmpName, valueList); fprintf(stdout, " Registry 1: Value: Type = RG_VALUETYPE_UNICODELIST\n"); fprintf(stdout, " Size = %d\n", size1); sal_uInt32 length = valueList.getLength(); OUString uStrValue; for (sal_uInt32 i=0; i valueList; key2.getLongListValue(tmpName, valueList); fprintf(stdout, " Registry 2: Value: Type = RG_VALUETYPE_LONGLIST\n"); fprintf(stdout, " Size = %d\n", size2); sal_uInt32 length = valueList.getLength(); for (sal_uInt32 i=0; i valueList; key2.getStringListValue(tmpName, valueList); fprintf(stdout, " Registry 2: Value: Type = RG_VALUETYPE_STRINGLIST\n"); fprintf(stdout, " Size = %d\n", size2); sal_uInt32 length = valueList.getLength(); for (sal_uInt32 i=0; i valueList; key2.getUnicodeListValue(tmpName, valueList); fprintf(stdout, " Registry 2: Value: Type = RG_VALUETYPE_UNICODELIST\n"); fprintf(stdout, " Size = %d\n", size2); sal_uInt32 length = valueList.getLength(); OUString uStrValue; for (sal_uInt32 i=0; i 0 ) exit(11); else exit(0); }