1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: regcompare.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_registry.hxx"
38 #include "registry/registry.hxx"
39 #include "registry/reader.hxx"
40 #include "registry/version.h"
41 #include <rtl/ustring.hxx>
42 #include <rtl/alloc.h>
43 #include <osl/process.h>
44 #include <osl/diagnose.h>
45 #include <osl/thread.h>
46 #include <osl/file.hxx>
51 #define SEPARATOR '\\'
54 using namespace ::rtl
;
55 using namespace ::osl
;
57 OUString
shortName(const OUString
& fullName
)
59 return fullName
.copy(fullName
.lastIndexOf('/') + 1);
62 sal_Bool
isFileUrl(const OString
& fileName
)
64 if (fileName
.indexOf("file://") == 0 )
69 OUString
convertToFileUrl(const OString
& fileName
)
71 if ( isFileUrl(fileName
) )
73 return OStringToOUString(fileName
, osl_getThreadTextEncoding());
76 OUString uUrlFileName
;
77 OUString
uFileName(fileName
.getStr(), fileName
.getLength(), osl_getThreadTextEncoding());
78 if ( fileName
.indexOf('.') == 0 || fileName
.indexOf(SEPARATOR
) < 0 )
81 if (osl_getProcessWorkingDir(&uWorkingDir
.pData
) != osl_Process_E_None
)
85 if (FileBase::getAbsoluteFileURL(uWorkingDir
, uFileName
, uUrlFileName
)
92 if (FileBase::getFileURLFromSystemPath(uFileName
, uUrlFileName
)
103 OUStringToOString(s, RTL_TEXTENCODING_UTF8).getStr()
105 OStringToOUString(s, RTL_TEXTENCODING_UTF8)
109 sal_Bool
operator()(const OUString
& str1
, const OUString
& str2
) const
111 return (str1
< str2
);
115 typedef ::std::set
< OUString
> StringSet
;
121 : m_bFullCheck(sal_False
)
122 , m_bForceOutput(sal_False
)
123 , m_bUnoTypeCheck(sal_False
)
124 , m_checkUnpublished(false)
129 sal_Bool
initOptions(int ac
, char* av
[], sal_Bool bCmdFile
=sal_False
);
131 OString
prepareHelp();
132 OString
prepareVersion();
134 const OString
& getProgramName()
135 { return m_program
; }
136 const OString
& getRegName1()
137 { return m_regName1
; }
138 const OString
& getRegName2()
139 { return m_regName2
; }
140 sal_Bool
isStartKeyValid()
141 { return (m_startKey
.getLength() > 0); };
142 const OString
& getStartKey()
143 { return m_startKey
; }
144 sal_Bool
existsExcludeKeys()
145 { return !m_excludeKeys
.empty(); };
146 StringSet
& getExcludeKeys()
147 { return m_excludeKeys
; }
148 sal_Bool
matchedWithExcludeKey( const OUString
& keyName
);
150 { return m_bFullCheck
; }
151 sal_Bool
forceOutput()
152 { return m_bForceOutput
; }
153 sal_Bool
unoTypeCheck()
154 { return m_bUnoTypeCheck
; }
155 bool checkUnpublished() const { return m_checkUnpublished
; }
161 StringSet m_excludeKeys
;
162 sal_Bool m_bFullCheck
;
163 sal_Bool m_bForceOutput
;
164 sal_Bool m_bUnoTypeCheck
;
165 bool m_checkUnpublished
;
168 sal_Bool
Options::initOptions(int ac
, char* av
[], sal_Bool bCmdFile
)
170 sal_Bool bRet
= sal_True
;
181 fprintf(stdout
, "%s", prepareHelp().getStr());
201 sal_Bool bFirst
= sal_True
;
205 } else if (av
[i
][2] != '1')
207 fprintf(stdout
, "%s: invalid option '%s'\n", m_program
.getStr(), av
[i
]);
209 if (av
[i
][3] == '\0')
211 if (i
< ac
- 1 && av
[i
+1][0] != '-')
217 fprintf(stdout
, "%s: invalid option '%s'\n", m_program
.getStr(), av
[i
]);
228 m_regName1
= OString(s
);
231 m_regName2
= OString(s
);
237 if (av
[i
][2] == '\0')
239 if (i
< ac
- 1 && av
[i
+1][0] != '-')
245 fprintf(stdout
, "%s: invalid option '%s'\n", m_program
.getStr(), av
[i
]);
253 m_startKey
= OString(s
);
257 if (av
[i
][2] == '\0')
259 if (i
< ac
- 1 && av
[i
+1][0] != '-')
265 fprintf(stdout
, "%s: invalid option '%s'\n", m_program
.getStr(), av
[i
]);
273 m_excludeKeys
.insert(S2U(s
));
277 if (av
[i
][2] != '\0')
279 fprintf(stdout
, "%s: invalid option '%s'\n", m_program
.getStr(), av
[i
]);
281 m_bFullCheck
= sal_True
;
285 if (av
[i
][2] != '\0')
287 fprintf(stdout
, "%s: invalid option '%s'\n", m_program
.getStr(), av
[i
]);
290 m_bForceOutput
= sal_True
;
294 if (av
[i
][2] != '\0')
296 fprintf(stdout
, "%s: invalid option '%s'\n", m_program
.getStr(), av
[i
]);
298 m_bUnoTypeCheck
= sal_True
;
302 if (av
[i
][2] != '\0')
304 fprintf(stdout
, "%s: invalid option '%s'\n", m_program
.getStr(), av
[i
]);
306 m_checkUnpublished
= true;
310 if (av
[i
][2] != '\0')
312 fprintf(stdout
, "%s: invalid option '%s'\n", m_program
.getStr(), av
[i
]);
316 fprintf(stdout
, "%s", prepareHelp().getStr());
321 fprintf(stdout
, "%s: unknown option '%s'\n", m_program
.getStr(), av
[i
]);
329 FILE* cmdFile
= fopen(av
[i
]+1, "r");
330 if( cmdFile
== NULL
)
332 fprintf(stdout
, "%s", prepareHelp().getStr());
340 while ( fscanf(cmdFile
, "%s", buffer
) != EOF
)
342 rargv
[rargc
]= strdup(buffer
);
347 bRet
= initOptions(rargc
, rargv
, bCmdFile
);
349 for (long j
=0; j
< rargc
; j
++)
356 fprintf(stdout
, "%s: unknown option '%s'\n", m_program
.getStr(), av
[i
]);
364 if ( m_regName1
.getLength() == 0 )
366 fprintf(stdout
, "%s: missing option '-r1'\n", m_program
.getStr());
369 if ( m_regName2
.getLength() == 0 )
371 fprintf(stdout
, "%s: missing option '-r2'\n", m_program
.getStr());
379 OString
Options::prepareHelp()
381 OString
help("\nusing: ");
382 help
+= m_program
+ " -r1<filename> -r2<filename> [-options] | @<filename>\n";
383 help
+= " -r1<filename> = filename specifies the name of the first registry.\n";
384 help
+= " -r2<filename> = filename specifies the name of the second registry.\n";
385 help
+= " @<filename> = filename specifies a command file.\n";
386 help
+= "Options:\n";
387 help
+= " -s<name> = name specifies the name of a start key. If no start key\n";
388 help
+= " |S<name> is specified the comparison starts with the root key.\n";
389 help
+= " -x<name> = name specifies the name of a key which won't be compared. All\n";
390 help
+= " |X<name> subkeys won't be compared also. This option can be used more than once.\n";
391 help
+= " -f|F = force the detailed output of any diffenrences. Default\n";
392 help
+= " is that only the number of differences is returned.\n";
393 help
+= " -c|C = make a complete check, that means any differences will be\n";
394 help
+= " detected. Default is only a compatibility check that means\n";
395 help
+= " only UNO typelibrary entries will be checked.\n";
396 help
+= " -t|T = make an UNO type compatiblity check. This means that registry 2\n";
397 help
+= " will be checked against registry 1. If a interface in r2 contains\n";
398 help
+= " more methods or the methods are in a different order as in r1, r2 is\n";
399 help
+= " incompatible to r1. But if a service in r2 supports more properties as\n";
400 help
+= " in r1 and the new properties are 'optonal' it is compatible.\n";
401 help
+= " -u|U = additionally check types that are unpublished in registry 1.\n";
402 help
+= " -h|-? = print this help message and exit.\n";
403 help
+= prepareVersion();
408 OString
Options::prepareVersion()
410 OString
version("\nSun Microsystems (R) ");
411 version
+= m_program
+ " Version 1.0\n\n";
415 sal_Bool
Options::matchedWithExcludeKey( const OUString
& keyName
)
417 if ( m_excludeKeys
.empty() )
420 StringSet::const_iterator iter
= m_excludeKeys
.begin();
421 StringSet::const_iterator end
= m_excludeKeys
.end();
423 while ( iter
!= end
)
425 if ( keyName
.indexOf(*iter
) == 0)
434 static Options options
;
436 static char const * getTypeClass(RTTypeClass typeClass
)
440 case RT_TYPE_INTERFACE
:
448 case RT_TYPE_EXCEPTION
:
450 case RT_TYPE_TYPEDEF
:
452 case RT_TYPE_SERVICE
:
456 case RT_TYPE_CONSTANTS
:
463 static OString
getFieldAccess(RTFieldAccess fieldAccess
)
466 if ( (fieldAccess
& RT_ACCESS_INVALID
) == RT_ACCESS_INVALID
)
468 ret
+= OString("INVALID");
470 if ( (fieldAccess
& RT_ACCESS_READONLY
) == RT_ACCESS_READONLY
)
472 ret
+= OString(ret
.getLength() > 0 ? ",READONLY" : "READONLY");
474 if ( (fieldAccess
& RT_ACCESS_OPTIONAL
) == RT_ACCESS_OPTIONAL
)
476 ret
+= OString(ret
.getLength() > 0 ? ",OPTIONAL" : "OPTIONAL");
478 if ( (fieldAccess
& RT_ACCESS_MAYBEVOID
) == RT_ACCESS_MAYBEVOID
)
480 ret
+= OString(ret
.getLength() > 0 ? ",MAYBEVOID" : "MAYBEVOID");
482 if ( (fieldAccess
& RT_ACCESS_BOUND
) == RT_ACCESS_BOUND
)
484 ret
+= OString(ret
.getLength() > 0 ? ",BOUND" : "BOUND");
486 if ( (fieldAccess
& RT_ACCESS_CONSTRAINED
) == RT_ACCESS_CONSTRAINED
)
488 ret
+= OString(ret
.getLength() > 0 ? ",CONSTRAINED" : "CONSTRAINED");
490 if ( (fieldAccess
& RT_ACCESS_TRANSIENT
) == RT_ACCESS_TRANSIENT
)
492 ret
+= OString(ret
.getLength() > 0 ? ",TRANSIENT" : "TRANSIENT");
494 if ( (fieldAccess
& RT_ACCESS_MAYBEAMBIGUOUS
) == RT_ACCESS_MAYBEAMBIGUOUS
)
496 ret
+= OString(ret
.getLength() > 0 ? ",MAYBEAMBIGUOUS" : "MAYBEAMBIGUOUS");
498 if ( (fieldAccess
& RT_ACCESS_MAYBEDEFAULT
) == RT_ACCESS_MAYBEDEFAULT
)
500 ret
+= OString(ret
.getLength() > 0 ? ",MAYBEDEFAULT" : "MAYBEDEFAULT");
502 if ( (fieldAccess
& RT_ACCESS_REMOVEABLE
) == RT_ACCESS_REMOVEABLE
)
504 ret
+= OString(ret
.getLength() > 0 ? ",REMOVEABLE" : "REMOVEABLE");
506 if ( (fieldAccess
& RT_ACCESS_ATTRIBUTE
) == RT_ACCESS_ATTRIBUTE
)
508 ret
+= OString(ret
.getLength() > 0 ? ",ATTRIBUTE" : "ATTRIBUTE");
510 if ( (fieldAccess
& RT_ACCESS_PROPERTY
) == RT_ACCESS_PROPERTY
)
512 ret
+= OString(ret
.getLength() > 0 ? ",PROPERTY" : "PROPERTY");
514 if ( (fieldAccess
& RT_ACCESS_CONST
) == RT_ACCESS_CONST
)
516 ret
+= OString(ret
.getLength() > 0 ? ",CONST" : "CONST");
518 if ( (fieldAccess
& RT_ACCESS_READWRITE
) == RT_ACCESS_READWRITE
)
520 ret
+= OString(ret
.getLength() > 0 ? ",READWRITE" : "READWRITE");
525 static char const * getConstValueType(RTConstValue
& constValue
)
527 switch (constValue
.m_type
)
541 // case RT_TYPE_INT64:
542 // return "sal_Int64";
543 // case RT_TYPE_UINT64:
544 // return "sal_uInt64";
550 return "sal_Unicode*";
555 static void printConstValue(RTConstValue
& constValue
)
557 switch (constValue
.m_type
)
560 fprintf(stdout
, "none");
563 fprintf(stdout
, "%s", constValue
.m_value
.aBool
? "TRUE" : "FALSE");
566 fprintf(stdout
, "%d", constValue
.m_value
.aByte
);
569 fprintf(stdout
, "%d", constValue
.m_value
.aShort
);
572 fprintf(stdout
, "%d", constValue
.m_value
.aUShort
);
577 sal::static_int_cast
< long >(constValue
.m_value
.aLong
));
582 sal::static_int_cast
< unsigned long >(
583 constValue
.m_value
.aULong
));
585 // case RT_TYPE_INT64:
586 // fprintf(stdout, "%d", constValue.m_value.aHyper);
587 // case RT_TYPE_UINT64:
588 // fprintf(stdout, "%d", constValue.m_value.aUHyper);
590 fprintf(stdout
, "%f", constValue
.m_value
.aFloat
);
593 fprintf(stdout
, "%f", constValue
.m_value
.aDouble
);
598 (rtl::OUStringToOString(
599 constValue
.m_value
.aString
, RTL_TEXTENCODING_UTF8
).
607 static sal_uInt32
checkConstValue(const OUString
& keyName
,
608 RTTypeClass typeClass
,
610 RTConstValue
& constValue1
,
611 RTConstValue
& constValue2
,
614 switch (constValue1
.m_type
)
616 case RT_TYPE_INVALID
:
619 if (constValue1
.m_value
.aBool
!= constValue2
.m_value
.aBool
)
621 if ( options
.forceOutput() && !options
.unoTypeCheck() )
625 fprintf(stdout
, "%s: %s\n", getTypeClass(typeClass
), U2S(keyName
));
628 fprintf(stdout
, " Field %d: Value1 = %s != Value2 = %s\n", index1
,
629 constValue1
.m_value
.aBool
? "TRUE" : "FALSE",
630 constValue2
.m_value
.aBool
? "TRUE" : "FALSE");
636 if (constValue1
.m_value
.aByte
!= constValue2
.m_value
.aByte
)
638 if ( options
.forceOutput() && !options
.unoTypeCheck() )
642 fprintf(stdout
, "%s: %s\n", getTypeClass(typeClass
), U2S(keyName
));
645 fprintf(stdout
, " Field %d: Value1 = %d != Value2 = %d\n", index1
,
646 constValue1
.m_value
.aByte
, constValue2
.m_value
.aByte
);
652 if (constValue1
.m_value
.aShort
!= constValue2
.m_value
.aShort
)
654 if ( options
.forceOutput() && !options
.unoTypeCheck() )
658 fprintf(stdout
, "%s: %s\n", getTypeClass(typeClass
), U2S(keyName
));
661 fprintf(stdout
, " Field %d: Value1 = %d != Value2 = %d\n", index1
,
662 constValue1
.m_value
.aShort
, constValue2
.m_value
.aShort
);
668 if (constValue1
.m_value
.aUShort
!= constValue2
.m_value
.aUShort
)
670 if ( options
.forceOutput() && !options
.unoTypeCheck() )
674 fprintf(stdout
, "%s: %s\n", getTypeClass(typeClass
), U2S(keyName
));
677 fprintf(stdout
, " Field %d: Value1 = %d != Value2 = %d\n", index1
,
678 constValue1
.m_value
.aUShort
, constValue2
.m_value
.aUShort
);
684 if (constValue1
.m_value
.aLong
!= constValue2
.m_value
.aLong
)
686 if ( options
.forceOutput() && !options
.unoTypeCheck() )
690 fprintf(stdout
, "%s: %s\n", getTypeClass(typeClass
), U2S(keyName
));
693 fprintf(stdout
, " Field %d: Value1 = %ld != Value2 = %ld\n", index1
,
694 sal::static_int_cast
< long >(constValue1
.m_value
.aLong
),
695 sal::static_int_cast
< long >(constValue2
.m_value
.aLong
));
701 if (constValue1
.m_value
.aULong
!= constValue2
.m_value
.aULong
)
703 if ( options
.forceOutput() && !options
.unoTypeCheck() )
707 fprintf(stdout
, "%s: %s\n", getTypeClass(typeClass
), U2S(keyName
));
710 fprintf(stdout
, " Field %d: Value1 = %lu != Value2 = %lu\n", index1
,
711 sal::static_int_cast
< unsigned long >(constValue1
.m_value
.aULong
),
712 sal::static_int_cast
< unsigned long >(constValue2
.m_value
.aULong
));
718 if (constValue1
.m_value
.aHyper
!= constValue2
.m_value
.aHyper
)
720 if ( options
.forceOutput() && !options
.unoTypeCheck() )
724 fprintf(stdout
, "%s: %s\n", getTypeClass(typeClass
), U2S(keyName
));
728 stdout
, " Field %d: Value1 = %s != Value2 = %s\n",
730 rtl::OUStringToOString(
731 rtl::OUString::valueOf(constValue1
.m_value
.aHyper
),
732 RTL_TEXTENCODING_ASCII_US
).getStr(),
733 rtl::OUStringToOString(
734 rtl::OUString::valueOf(constValue2
.m_value
.aHyper
),
735 RTL_TEXTENCODING_ASCII_US
).getStr());
741 if (constValue1
.m_value
.aUHyper
!= constValue2
.m_value
.aUHyper
)
743 if ( options
.forceOutput() && !options
.unoTypeCheck() )
747 fprintf(stdout
, "%s: %s\n", getTypeClass(typeClass
), U2S(keyName
));
751 stdout
, " Field %d: Value1 = %s != Value2 = %s\n",
753 rtl::OUStringToOString(
754 rtl::OUString::valueOf(
755 static_cast< sal_Int64
>(
756 constValue1
.m_value
.aUHyper
)),
757 RTL_TEXTENCODING_ASCII_US
).getStr(),
758 rtl::OUStringToOString(
759 rtl::OUString::valueOf(
760 static_cast< sal_Int64
>(
761 constValue2
.m_value
.aUHyper
)),
762 RTL_TEXTENCODING_ASCII_US
).getStr());
763 // printing the unsigned values as signed should be
770 if (constValue1
.m_value
.aFloat
!= constValue2
.m_value
.aFloat
)
772 if ( options
.forceOutput() && !options
.unoTypeCheck() )
776 fprintf(stdout
, "%s: %s\n", getTypeClass(typeClass
), U2S(keyName
));
779 fprintf(stdout
, " Field %d: Value1 = %f != Value2 = %f\n", index1
,
780 constValue1
.m_value
.aFloat
, constValue2
.m_value
.aFloat
);
786 if (constValue1
.m_value
.aDouble
!= constValue2
.m_value
.aDouble
)
788 if ( options
.forceOutput() && !options
.unoTypeCheck() )
792 fprintf(stdout
, "%s: %s\n", getTypeClass(typeClass
), U2S(keyName
));
795 fprintf(stdout
, " Field %d: Value1 = %f != Value2 = %f\n", index1
,
796 constValue1
.m_value
.aDouble
, constValue2
.m_value
.aDouble
);
808 static sal_uInt32
checkField(const OUString
& keyName
,
809 RTTypeClass typeClass
,
811 typereg::Reader
& reader1
,
812 typereg::Reader
& reader2
,
816 sal_uInt32 nError
= 0;
817 if ( reader1
.getFieldName(index1
) !=
818 reader2
.getFieldName(index2
) )
820 if ( options
.forceOutput() && !options
.unoTypeCheck() )
824 fprintf(stdout
, "%s: %s\n", getTypeClass(typeClass
), U2S(keyName
));
827 fprintf(stdout
, " Field %d: Name1 = %s != Name2 = %s\n", index1
,
828 U2S(reader1
.getFieldName(index1
)), U2S(reader2
.getFieldName(index2
)));
832 if ( reader1
.getFieldTypeName(index1
) !=
833 reader2
.getFieldTypeName(index2
) )
835 if ( options
.forceOutput() && !options
.unoTypeCheck() )
839 fprintf(stdout
, "%s: %s\n", getTypeClass(typeClass
), U2S(keyName
));
842 fprintf(stdout
, " Field %d: Type1 = %s != Type2 = %s\n", index1
,
843 U2S(reader1
.getFieldTypeName(index1
)), U2S(reader2
.getFieldTypeName(index2
)));
848 RTConstValue constValue1
= reader1
.getFieldValue(index1
);
849 RTConstValue constValue2
= reader2
.getFieldValue(index2
);
850 if ( constValue1
.m_type
!= constValue2
.m_type
)
852 if ( options
.forceOutput() && !options
.unoTypeCheck() )
856 fprintf(stdout
, "%s: %s\n", getTypeClass(typeClass
), U2S(keyName
));
859 fprintf(stdout
, " Field %d: Access1 = %s != Access2 = %s\n", index1
,
860 getConstValueType(constValue1
), getConstValueType(constValue2
));
861 fprintf(stdout
, " Field %d: Value1 = ", index1
);
862 printConstValue(constValue1
);
863 fprintf(stdout
, " != Value2 = ");
864 printConstValue(constValue1
);
865 fprintf(stdout
, "\n;");
870 nError
+= checkConstValue(keyName
, typeClass
, bDump
, constValue1
, constValue2
, index1
);
874 if ( reader1
.getFieldFlags(index1
) != reader2
.getFieldFlags(index2
) )
876 if ( options
.forceOutput() && !options
.unoTypeCheck() )
880 fprintf(stdout
, "%s: %s\n", getTypeClass(typeClass
), U2S(keyName
));
883 fprintf(stdout
, " Field %d: FieldAccess1 = %s != FieldAccess2 = %s\n", index1
,
884 getFieldAccess(reader1
.getFieldFlags(index1
)).getStr(),
885 getFieldAccess(reader1
.getFieldFlags(index2
)).getStr());
890 if ( options
.fullCheck() &&
891 (reader1
.getFieldDocumentation(index1
) != reader2
.getFieldDocumentation(index2
)) )
893 if ( options
.forceOutput() && !options
.unoTypeCheck() )
897 fprintf(stdout
, "%s: %s\n", getTypeClass(typeClass
), U2S(keyName
));
900 fprintf(stdout
, " Field %d: Doku1 = %s\n Doku2 = %s\n", index1
,
901 U2S(reader1
.getFieldDocumentation(index1
)), U2S(reader2
.getFieldDocumentation(index2
)));
908 static char const * getMethodMode(RTMethodMode methodMode
)
910 switch ( methodMode
)
914 case RT_MODE_ONEWAY_CONST
:
915 return "ONEWAY,CONST";
918 case RT_MODE_TWOWAY_CONST
:
925 static char const * getParamMode(RTParamMode paramMode
)
940 static sal_uInt32
checkMethod(const OUString
& keyName
,
941 RTTypeClass typeClass
,
943 typereg::Reader
& reader1
,
944 typereg::Reader
& reader2
,
947 sal_uInt32 nError
= 0;
948 if ( reader1
.getMethodName(index
) !=
949 reader2
.getMethodName(index
) )
951 if ( options
.forceOutput() )
955 fprintf(stdout
, "%s: %s\n", getTypeClass(typeClass
), U2S(keyName
));
958 fprintf(stdout
, " Method1 %d: Name1 = %s != Name2 = %s\n", index
,
959 U2S(reader1
.getMethodName(index
)),
960 U2S(reader2
.getMethodName(index
)));
965 if ( reader1
.getMethodReturnTypeName(index
) !=
966 reader2
.getMethodReturnTypeName(index
) )
968 if ( options
.forceOutput() )
972 fprintf(stdout
, "%s: %s\n", getTypeClass(typeClass
), U2S(keyName
));
975 fprintf(stdout
, " Method1 %d: ReturnType1 = %s != ReturnType2 = %s\n", index
,
976 U2S(reader1
.getMethodReturnTypeName(index
)),
977 U2S(reader2
.getMethodReturnTypeName(index
)));
982 sal_uInt16 nParams1
= (sal_uInt16
)reader1
.getMethodParameterCount(index
);
983 sal_uInt16 nParams2
= (sal_uInt16
)reader2
.getMethodParameterCount(index
);
984 if ( nParams1
!= nParams2
)
986 if ( options
.forceOutput() )
990 fprintf(stdout
, "%s: %s\n", getTypeClass(typeClass
), U2S(keyName
));
993 fprintf(stdout
, " Method %d : nParameters1 = %d != nParameters2 = %d\n", index
, nParams1
, nParams2
);
998 for (i
=0; i
< nParams1
&& i
< nParams2
; i
++)
1000 if ( reader1
.getMethodParameterTypeName(index
, i
) != reader2
.getMethodParameterTypeName(index
, i
) )
1002 if ( options
.forceOutput() )
1006 fprintf(stdout
, "%s: %s\n", getTypeClass(typeClass
), U2S(keyName
));
1009 fprintf(stdout
, " Method %d, Parameter %d: Type1 = %s != Type2 = %s\n", index
, i
,
1010 U2S(reader1
.getMethodParameterTypeName(index
, i
)),
1011 U2S(reader2
.getMethodParameterTypeName(index
, i
)));
1015 if ( options
.fullCheck() &&
1016 (reader1
.getMethodParameterName(index
, i
) != reader2
.getMethodParameterName(index
, i
)) )
1018 if ( options
.forceOutput() )
1022 fprintf(stdout
, "%s: %s\n", getTypeClass(typeClass
), U2S(keyName
));
1025 fprintf(stdout
, " Method %d, Parameter %d: Name1 = %s != Name2 = %s\n", index
, i
,
1026 U2S(reader1
.getMethodParameterName(index
, i
)),
1027 U2S(reader2
.getMethodParameterName(index
, i
)));
1031 if ( reader1
.getMethodParameterFlags(index
, i
) != reader2
.getMethodParameterFlags(index
, i
) )
1033 if ( options
.forceOutput() )
1037 fprintf(stdout
, "%s: %s\n", getTypeClass(typeClass
), U2S(keyName
));
1040 fprintf(stdout
, " Method %d, Parameter %d: Mode1 = %s != Mode2 = %s\n", index
, i
,
1041 getParamMode(reader1
.getMethodParameterFlags(index
, i
)),
1042 getParamMode(reader2
.getMethodParameterFlags(index
, i
)));
1047 if ( i
< nParams1
&& options
.forceOutput() )
1051 fprintf(stdout
, "%s: %s\n", getTypeClass(typeClass
), U2S(keyName
));
1054 fprintf(stdout
, " Registry1: Method %d contains %d more parameters\n", index
, nParams1
- i
);
1056 if ( i
< nParams2
&& options
.forceOutput() )
1060 fprintf(stdout
, "%s: %s\n", getTypeClass(typeClass
), U2S(keyName
));
1063 fprintf(stdout
, " Registry2: Method %d contains %d more parameters\n", index
, nParams2
- i
);
1066 sal_uInt16 nExcep1
= (sal_uInt16
)reader1
.getMethodExceptionCount(index
);
1067 sal_uInt16 nExcep2
= (sal_uInt16
)reader2
.getMethodExceptionCount(index
);
1068 if ( nExcep1
!= nExcep2
)
1070 if ( options
.forceOutput() )
1074 fprintf(stdout
, "%s: %s\n", getTypeClass(typeClass
), U2S(keyName
));
1077 fprintf(stdout
, " nExceptions1 = %d != nExceptions2 = %d\n", nExcep1
, nExcep2
);
1081 for (i
=0; i
< nExcep1
&& i
< nExcep2
; i
++)
1083 if ( reader1
.getMethodExceptionTypeName(index
, i
) != reader2
.getMethodExceptionTypeName(index
, i
) )
1085 if ( options
.forceOutput() )
1089 fprintf(stdout
, "%s: %s\n", getTypeClass(typeClass
), U2S(keyName
));
1092 fprintf(stdout
, " Method %d, Exception %d: Name1 = %s != Name2 = %s\n", index
, i
,
1093 U2S(reader1
.getMethodExceptionTypeName(index
, i
)),
1094 U2S(reader2
.getMethodExceptionTypeName(index
, i
)));
1099 if ( i
< nExcep1
&& options
.forceOutput() )
1103 fprintf(stdout
, "%s: %s\n", getTypeClass(typeClass
), U2S(keyName
));
1106 fprintf(stdout
, " Registry1: Method %d contains %d more exceptions\n", index
, nExcep1
- i
);
1108 if ( i
< nExcep2
&& options
.forceOutput() )
1112 fprintf(stdout
, "%s: %s\n", getTypeClass(typeClass
), U2S(keyName
));
1115 fprintf(stdout
, " Registry2: Method %d contains %d more exceptions\n", index
, nExcep2
- i
);
1118 if ( reader1
.getMethodFlags(index
) != reader2
.getMethodFlags(index
) )
1120 if ( options
.forceOutput() )
1124 fprintf(stdout
, "%s: %s\n", getTypeClass(typeClass
), U2S(keyName
));
1127 fprintf(stdout
, " Method %d: Mode1 = %s != Mode2 = %s\n", index
,
1128 getMethodMode(reader1
.getMethodFlags(index
)),
1129 getMethodMode(reader2
.getMethodFlags(index
)));
1134 if ( options
.fullCheck() &&
1135 (reader1
.getMethodDocumentation(index
) != reader2
.getMethodDocumentation(index
)) )
1137 if ( options
.forceOutput() )
1141 fprintf(stdout
, "%s: %s\n", getTypeClass(typeClass
), U2S(keyName
));
1144 fprintf(stdout
, " Method %d: Doku1 = %s\n Doku2 = %s\n", index
,
1145 U2S(reader1
.getMethodDocumentation(index
)),
1146 U2S(reader2
.getMethodDocumentation(index
)));
1153 static char const * getReferenceType(RTReferenceType refType
)
1157 case RT_REF_SUPPORTS
:
1158 return "RT_REF_SUPPORTS";
1159 case RT_REF_OBSERVES
:
1160 return "RT_REF_OBSERVES";
1161 case RT_REF_EXPORTS
:
1162 return "RT_REF_EXPORTS";
1164 return "RT_REF_NEEDS";
1166 return "RT_REF_INVALID";
1170 static sal_uInt32
checkReference(const OUString
& keyName
,
1171 RTTypeClass typeClass
,
1173 typereg::Reader
& reader1
,
1174 typereg::Reader
& reader2
,
1178 sal_uInt32 nError
= 0;
1179 if ( reader1
.getReferenceTypeName(index1
) !=
1180 reader2
.getReferenceTypeName(index2
) )
1182 if ( options
.forceOutput() && !options
.unoTypeCheck() )
1186 fprintf(stdout
, "%s: %s\n", getTypeClass(typeClass
), U2S(keyName
));
1189 fprintf(stdout
, " Reference %d: Name1 = %s != Name2 = %s\n", index1
,
1190 U2S(reader1
.getReferenceTypeName(index1
)),
1191 U2S(reader2
.getReferenceTypeName(index2
)));
1195 if ( reader1
.getReferenceTypeName(index1
) !=
1196 reader2
.getReferenceTypeName(index2
) )
1198 if ( options
.forceOutput() && !options
.unoTypeCheck() )
1202 fprintf(stdout
, "%s: %s\n", getTypeClass(typeClass
), U2S(keyName
));
1205 fprintf(stdout
, " Reference %d: Type1 = %s != Type2 = %s\n", index1
,
1206 getReferenceType(reader1
.getReferenceSort(index1
)),
1207 getReferenceType(reader2
.getReferenceSort(index2
)));
1211 if ( options
.fullCheck() &&
1212 (reader1
.getReferenceDocumentation(index1
) != reader2
.getReferenceDocumentation(index2
)) )
1214 if ( options
.forceOutput() && !options
.unoTypeCheck() )
1218 fprintf(stdout
, "%s: %s\n", getTypeClass(typeClass
), U2S(keyName
));
1221 fprintf(stdout
, " Reference %d: Doku1 = %s\n Doku2 = %s\n", index1
,
1222 U2S(reader1
.getReferenceDocumentation(index1
)),
1223 U2S(reader2
.getReferenceDocumentation(index2
)));
1227 if ( reader1
.getReferenceFlags(index1
) !=
1228 reader2
.getReferenceFlags(index2
) )
1230 if ( options
.forceOutput() && !options
.unoTypeCheck() )
1234 fprintf(stdout
, "%s: %s\n", getTypeClass(typeClass
), U2S(keyName
));
1237 fprintf(stdout
, " Reference %d: Access1 = %s != Access2 = %s\n", index1
,
1238 getFieldAccess(reader1
.getReferenceFlags(index1
)).getStr(),
1239 getFieldAccess(reader1
.getReferenceFlags(index2
)).getStr());
1246 static sal_uInt32
checkFieldsWithoutOrder(const OUString
& keyName
,
1247 RTTypeClass typeClass
,
1249 typereg::Reader
& reader1
,
1250 typereg::Reader
& reader2
)
1252 sal_uInt32 nError
= 0;
1254 sal_uInt16 nFields1
= (sal_uInt16
)reader1
.getFieldCount();
1255 sal_uInt16 nFields2
= (sal_uInt16
)reader2
.getFieldCount();
1256 sal_uInt16 i
=0, j
=0;
1258 if ( nFields1
> nFields2
)
1260 if ( options
.forceOutput() )
1264 fprintf(stdout
, "%s: %s\n", getTypeClass(typeClass
), U2S(keyName
));
1267 fprintf(stdout
, " %s1 contains %d more properties as %s2\n",
1268 getTypeClass(typeClass
), nFields1
-nFields2
, getTypeClass(typeClass
));
1272 sal_Bool bFound
= sal_False
;
1273 ::std::set
< sal_uInt16
> moreProps
;
1275 for (i
=0; i
< nFields1
; i
++)
1277 for (j
=0; j
< nFields2
; j
++)
1279 if (!checkField(keyName
, typeClass
, bDump
, reader1
, reader2
, i
, j
))
1282 moreProps
.insert(j
);
1288 if (options
.forceOutput())
1292 fprintf(stdout
, "%s: %s\n", getTypeClass(typeClass
), U2S(keyName
));
1295 fprintf(stdout
, " incompatible change: Field %d ('%s') of r1 is not longer a property of this %s in r2\n",
1296 i
, U2S(shortName(reader1
.getFieldName(i
))), getTypeClass(typeClass
));
1305 if ( typeClass
== RT_TYPE_SERVICE
&& !moreProps
.empty() )
1307 for (j
=0; j
< nFields2
; j
++)
1309 if ( moreProps
.find(j
) == moreProps
.end() )
1311 if ( (reader2
.getFieldFlags(j
) & RT_ACCESS_OPTIONAL
) != RT_ACCESS_OPTIONAL
)
1313 if ( options
.forceOutput() )
1317 fprintf(stdout
, "%s: %s\n", getTypeClass(typeClass
), U2S(keyName
));
1320 fprintf(stdout
, " incompatible change: Field %d ('%s') of r2 is a new property compared to this %s in r1 and is not 'optional'\n",
1321 j
, U2S(shortName(reader2
.getFieldName(j
))), getTypeClass(typeClass
));
1332 static sal_uInt32
checkBlob(const OUString
& keyName
, typereg::Reader
& reader1
, sal_uInt32 size1
,
1333 typereg::Reader
& reader2
, sal_uInt32 size2
)
1335 sal_uInt32 nError
= 0;
1336 sal_Bool bDump
= sal_True
;
1338 if ( options
.fullCheck() && (size1
!= size2
) )
1340 if ( options
.forceOutput() )
1343 stdout
, " Size1 = %lu Size2 = %lu\n",
1344 sal::static_int_cast
< unsigned long >(size1
),
1345 sal::static_int_cast
< unsigned long >(size2
));
1348 if (reader1
.isPublished()) {
1349 if (!reader2
.isPublished()) {
1350 if (options
.forceOutput()) {
1352 fprintf(stdout
, "?: %s\n", U2S(keyName
));
1355 fprintf(stdout
, " published in 1 but unpublished in 2\n");
1359 } else if (!options
.checkUnpublished()) {
1362 if ( reader1
.getTypeClass() != reader2
.getTypeClass() )
1364 if ( options
.forceOutput() )
1367 fprintf(stdout
, "?: %s\n", U2S(keyName
));
1370 fprintf(stdout
, " TypeClass1 = %s != TypeClass2 = %s\n",
1371 getTypeClass(reader1
.getTypeClass()),
1372 getTypeClass(reader2
.getTypeClass()));
1377 RTTypeClass typeClass
= reader1
.getTypeClass();
1379 if ( reader1
.getTypeName() != reader2
.getTypeName() )
1381 if ( options
.forceOutput() )
1385 fprintf(stdout
, "%s: %s\n", getTypeClass(typeClass
), U2S(keyName
));
1388 fprintf(stdout
, " TypeName1 = %s != TypeName2 = %s\n",
1389 U2S(reader1
.getTypeName()), U2S(reader2
.getTypeName()));
1393 if ( (typeClass
== RT_TYPE_INTERFACE
||
1394 typeClass
== RT_TYPE_STRUCT
||
1395 typeClass
== RT_TYPE_EXCEPTION
) )
1397 if (reader1
.getSuperTypeCount() != reader2
.getSuperTypeCount()) {
1400 stdout
, "%s: %s\n", getTypeClass(typeClass
), U2S(keyName
));
1404 stdout
, " SuperTypeCount1 = %d != SuperTypeCount2 = %d\n",
1405 static_cast< int >(reader1
.getSuperTypeCount()),
1406 static_cast< int >(reader2
.getSuperTypeCount()));
1409 for (sal_Int16 i
= 0; i
< reader1
.getSuperTypeCount(); ++i
) {
1410 if (reader1
.getSuperTypeName(i
) != reader2
.getSuperTypeName(i
))
1412 if ( options
.forceOutput() )
1416 fprintf(stdout
, "%s: %s\n", getTypeClass(typeClass
), U2S(keyName
));
1419 fprintf(stdout
, " SuperTypeName1 = %s != SuperTypeName2 = %s\n",
1420 U2S(reader1
.getSuperTypeName(i
)), U2S(reader2
.getSuperTypeName(i
)));
1427 sal_uInt16 nFields1
= (sal_uInt16
)reader1
.getFieldCount();
1428 sal_uInt16 nFields2
= (sal_uInt16
)reader2
.getFieldCount();
1429 sal_Bool bCheckNormal
= sal_True
;
1431 if ( (typeClass
== RT_TYPE_SERVICE
||
1432 typeClass
== RT_TYPE_MODULE
||
1433 typeClass
== RT_TYPE_CONSTANTS
) && options
.unoTypeCheck() )
1435 bCheckNormal
= sal_False
;
1440 if ( nFields1
!= nFields2
)
1442 if ( options
.forceOutput() )
1446 fprintf(stdout
, "%s: %s\n", getTypeClass(typeClass
), U2S(keyName
));
1449 fprintf(stdout
, " nFields1 = %d != nFields2 = %d\n", nFields1
, nFields2
);
1454 for (i
=0; i
< nFields1
&& i
< nFields2
; i
++)
1456 nError
+= checkField(keyName
, typeClass
, bDump
, reader1
, reader2
, i
, i
);
1458 if ( i
< nFields1
&& options
.forceOutput() )
1462 fprintf(stdout
, "%s: %s\n", getTypeClass(typeClass
), U2S(keyName
));
1465 fprintf(stdout
, " Registry1 contains %d more fields\n", nFields1
- i
);
1467 if ( i
< nFields2
&& options
.forceOutput() )
1471 fprintf(stdout
, "%s: %s\n", getTypeClass(typeClass
), U2S(keyName
));
1474 fprintf(stdout
, " Registry2 contains %d more fields\n", nFields2
- i
);
1478 nError
+= checkFieldsWithoutOrder(keyName
, typeClass
, bDump
, reader1
, reader2
);
1481 if ( typeClass
== RT_TYPE_INTERFACE
)
1483 sal_uInt16 nMethods1
= (sal_uInt16
)reader1
.getMethodCount();
1484 sal_uInt16 nMethods2
= (sal_uInt16
)reader2
.getMethodCount();
1485 if ( nMethods1
!= nMethods2
)
1487 if ( options
.forceOutput() )
1491 fprintf(stdout
, "%s: %s\n", getTypeClass(typeClass
), U2S(keyName
));
1494 fprintf(stdout
, " nMethods1 = %d != nMethods2 = %d\n", nMethods1
, nMethods2
);
1499 for (i
=0; i
< nMethods1
&& i
< nMethods2
; i
++)
1501 nError
+= checkMethod(keyName
, typeClass
, bDump
, reader1
, reader2
, i
);
1503 if ( i
< nMethods1
&& options
.forceOutput() )
1505 fprintf(stdout
, " Registry1 contains %d more methods\n", nMethods1
- i
);
1507 if ( i
< nMethods2
&& options
.forceOutput() )
1509 fprintf(stdout
, " Registry2 contains %d more methods\n", nMethods2
- i
);
1512 if ( typeClass
== RT_TYPE_SERVICE
)
1514 sal_uInt16 nReference1
= (sal_uInt16
)reader1
.getReferenceCount();
1515 sal_uInt16 nReference2
= (sal_uInt16
)reader2
.getReferenceCount();
1517 if ( !bCheckNormal
)
1519 sal_uInt16 i
=0, j
=0;
1521 if ( nReference1
> nReference2
)
1523 if ( options
.forceOutput() )
1527 fprintf(stdout
, "%s: %s\n", getTypeClass(typeClass
), U2S(keyName
));
1530 fprintf(stdout
, " service1 contains %d more references as service2\n",
1531 nReference1
-nReference2
);
1535 sal_Bool bFound
= sal_False
;
1536 ::std::set
< sal_uInt16
> moreReferences
;
1538 for (i
=0; i
< nReference1
; i
++)
1540 for (j
=0; j
< nReference2
; j
++)
1542 if (!checkReference(keyName
, typeClass
, bDump
, reader1
, reader2
, i
, j
))
1545 moreReferences
.insert(j
);
1551 if (options
.forceOutput())
1555 fprintf(stdout
, "%s: %s\n", getTypeClass(typeClass
), U2S(keyName
));
1558 fprintf(stdout
, " incompatible change: Reference %d ('%s') in 'r1' is not longer a reference of this service in 'r2'\n",
1559 i
, U2S(shortName(reader1
.getReferenceTypeName(i
))));
1568 if ( !moreReferences
.empty() )
1570 for (j
=0; j
< nReference2
; j
++)
1572 if ( moreReferences
.find(j
) == moreReferences
.end() )
1574 if ( (reader2
.getReferenceFlags(j
) & RT_ACCESS_OPTIONAL
) != RT_ACCESS_OPTIONAL
)
1576 if ( options
.forceOutput() )
1580 fprintf(stdout
, "%s: %s\n", getTypeClass(typeClass
), U2S(keyName
));
1583 fprintf(stdout
, " incompatible change: Reference %d ('%s') of r2 is a new reference compared to this service in r1 and is not 'optional'\n",
1584 j
, U2S(shortName(reader2
.getReferenceTypeName(j
))));
1593 if ( nReference1
!= nReference2
)
1595 if ( options
.forceOutput() )
1599 fprintf(stdout
, "%s: %s\n", getTypeClass(typeClass
), U2S(keyName
));
1602 fprintf(stdout
, " nReferences1 = %d != nReferences2 = %d\n", nReference1
, nReference2
);
1607 for (i
=0; i
< nReference1
&& i
< nReference2
; i
++)
1609 nError
+= checkReference(keyName
, typeClass
, bDump
, reader1
, reader2
, i
, i
);
1611 if ( i
< nReference1
&& options
.forceOutput() )
1613 fprintf(stdout
, " Registry1 contains %d more references\n", nReference1
- i
);
1615 if ( i
< nReference2
&& options
.forceOutput() )
1617 fprintf(stdout
, " Registry2 contains %d more references\n", nReference2
- i
);
1622 if ( options
.fullCheck() && (reader1
.getDocumentation() != reader2
.getDocumentation()) )
1624 if ( options
.forceOutput() )
1628 fprintf(stdout
, "%s: %s\n", getTypeClass(typeClass
), U2S(keyName
));
1631 fprintf(stdout
, " Doku1 = %s\n Doku2 = %s\n",
1632 U2S(reader1
.getDocumentation()), U2S(reader2
.getDocumentation()));
1638 (!keyName.compareTo(OUString::createFromAscii("/UCR/drafts"), 11) ||
1639 !keyName.compareTo(OUString::createFromAscii("/drafts"), 7)) )
1641 if ( options.forceOutput() )
1645 fprintf(stdout, "%s: %s\n", getTypeClass(typeClass), U2S(keyName));
1648 fprintf(stdout, " Note: \"drafts\" type changed incompatible, no effect to the final API\n");
1656 static sal_uInt32
checkValueDifference(RegistryKey
& key1
, RegValueType valueType1
, sal_uInt32 size1
,
1657 RegistryKey
& key2
, RegValueType valueType2
, sal_uInt32 size2
)
1660 sal_uInt32 nError
= 0;
1662 if ( valueType1
== valueType2
)
1664 sal_Bool bEqual
= sal_True
;
1667 case RG_VALUETYPE_LONGLIST
:
1669 RegistryValueList
<sal_Int32
> valueList1
;
1670 RegistryValueList
<sal_Int32
> valueList2
;
1671 key1
.getLongListValue(tmpName
, valueList1
);
1672 key2
.getLongListValue(tmpName
, valueList2
);
1673 sal_uInt32 length1
= valueList1
.getLength();
1674 sal_uInt32 length2
= valueList1
.getLength();
1675 if ( length1
!= length2
)
1680 for (sal_uInt32 i
=0; i
<length1
; i
++)
1682 if ( valueList1
.getElement(i
) != valueList2
.getElement(i
) )
1690 case RG_VALUETYPE_STRINGLIST
:
1692 RegistryValueList
<sal_Char
*> valueList1
;
1693 RegistryValueList
<sal_Char
*> valueList2
;
1694 key1
.getStringListValue(tmpName
, valueList1
);
1695 key2
.getStringListValue(tmpName
, valueList2
);
1696 sal_uInt32 length1
= valueList1
.getLength();
1697 sal_uInt32 length2
= valueList1
.getLength();
1698 if ( length1
!= length2
)
1703 for (sal_uInt32 i
=0; i
<length1
; i
++)
1705 if ( strcmp(valueList1
.getElement(i
), valueList2
.getElement(i
)) != 0 )
1713 case RG_VALUETYPE_UNICODELIST
:
1715 RegistryValueList
<sal_Unicode
*> valueList1
;
1716 RegistryValueList
<sal_Unicode
*> valueList2
;
1717 key1
.getUnicodeListValue(tmpName
, valueList1
);
1718 key2
.getUnicodeListValue(tmpName
, valueList2
);
1719 sal_uInt32 length1
= valueList1
.getLength();
1720 sal_uInt32 length2
= valueList1
.getLength();
1721 if ( length1
!= length2
)
1726 for (sal_uInt32 i
=0; i
<length1
; i
++)
1728 if ( rtl_ustr_compare(valueList1
.getElement(i
), valueList2
.getElement(i
)) != 0 )
1742 RegValue value1
= rtl_allocateMemory(size1
);
1743 RegValue value2
= rtl_allocateMemory(size2
);
1745 key1
.getValue(tmpName
, value1
);
1746 key2
.getValue(tmpName
, value2
);
1748 bEqual
= (rtl_compareMemory(value1
, value2
, size1
) == 0 );
1750 if ( !bEqual
&& valueType1
== RG_VALUETYPE_BINARY
&& valueType2
== RG_VALUETYPE_BINARY
)
1752 typereg::Reader
reader1(
1753 value1
, size1
, false, TYPEREG_VERSION_1
);
1754 typereg::Reader
reader2(
1755 value2
, size2
, false, TYPEREG_VERSION_1
);
1757 if ( reader1
.isValid() && reader2
.isValid() )
1759 return checkBlob(key1
.getName(), reader1
, size1
, reader2
, size2
);
1763 rtl_freeMemory(value1
);
1764 rtl_freeMemory(value2
);
1771 if ( options
.forceOutput() )
1773 fprintf(stdout
, "Difference: key values of key \"%s\" are different\n",
1774 U2S(key1
.getName()));
1781 if ( options
.forceOutput() )
1785 case RG_VALUETYPE_NOT_DEFINED
:
1786 fprintf(stdout
, " Registry 1: key has no value\n");
1788 case RG_VALUETYPE_LONG
:
1789 case RG_VALUETYPE_STRING
:
1790 case RG_VALUETYPE_UNICODE
:
1792 RegValue value1
= rtl_allocateMemory(size1
);
1793 key1
.getValue(tmpName
, value1
);
1797 case RG_VALUETYPE_LONG
:
1798 fprintf(stdout
, " Registry 1: Value: Type = RG_VALUETYPE_LONG\n");
1800 stdout
, " Size = %lu\n",
1801 sal::static_int_cast
< unsigned long >(size1
));
1802 fprintf(stdout
, " Data = %p\n", value1
);
1804 case RG_VALUETYPE_STRING
:
1805 fprintf(stdout
, " Registry 1: Value: Type = RG_VALUETYPE_STRING\n");
1807 stdout
, " Size = %lu\n",
1808 sal::static_int_cast
< unsigned long >(size1
));
1809 fprintf(stdout
, " Data = \"%s\"\n", (sal_Char
*)value1
);
1811 case RG_VALUETYPE_UNICODE
:
1813 OUString
uStrValue((sal_Unicode
*)value1
);
1814 fprintf(stdout
, " Registry 1: Value: Type = RG_VALUETYPE_UNICODE\n");
1816 stdout
, " Size = %lu\n",
1817 sal::static_int_cast
< unsigned long >(size1
));
1818 fprintf(stdout
, " Data = \"%s\"\n", U2S(uStrValue
));
1826 rtl_freeMemory(value1
);
1829 case RG_VALUETYPE_BINARY
:
1830 fprintf(stdout
, " Registry 1: Value: Type = RG_VALUETYPE_BINARY\n");
1832 case RG_VALUETYPE_LONGLIST
:
1834 RegistryValueList
<sal_Int32
> valueList
;
1835 key1
.getLongListValue(tmpName
, valueList
);
1836 fprintf(stdout
, " Registry 1: Value: Type = RG_VALUETYPE_LONGLIST\n");
1838 stdout
, " Size = %lu\n",
1839 sal::static_int_cast
< unsigned long >(size1
));
1840 sal_uInt32 length
= valueList
.getLength();
1841 for (sal_uInt32 i
=0; i
<length
; i
++)
1844 stdout
, " Data[%lu] = %ld\n",
1845 sal::static_int_cast
< unsigned long >(i
),
1846 sal::static_int_cast
< long >(valueList
.getElement(i
)));
1850 case RG_VALUETYPE_STRINGLIST
:
1852 RegistryValueList
<sal_Char
*> valueList
;
1853 key1
.getStringListValue(tmpName
, valueList
);
1854 fprintf(stdout
, " Registry 1: Value: Type = RG_VALUETYPE_STRINGLIST\n");
1856 stdout
, " Size = %lu\n",
1857 sal::static_int_cast
< unsigned long >(size1
));
1858 sal_uInt32 length
= valueList
.getLength();
1859 for (sal_uInt32 i
=0; i
<length
; i
++)
1862 stdout
, " Data[%lu] = \"%s\"\n",
1863 sal::static_int_cast
< unsigned long >(i
),
1864 valueList
.getElement(i
));
1868 case RG_VALUETYPE_UNICODELIST
:
1870 RegistryValueList
<sal_Unicode
*> valueList
;
1871 key1
.getUnicodeListValue(tmpName
, valueList
);
1872 fprintf(stdout
, " Registry 1: Value: Type = RG_VALUETYPE_UNICODELIST\n");
1874 stdout
, " Size = %lu\n",
1875 sal::static_int_cast
< unsigned long >(size1
));
1876 sal_uInt32 length
= valueList
.getLength();
1878 for (sal_uInt32 i
=0; i
<length
; i
++)
1880 uStrValue
= OUString(valueList
.getElement(i
));
1882 stdout
, " Data[%lu] = \"%s\"\n",
1883 sal::static_int_cast
< unsigned long >(i
), U2S(uStrValue
));
1891 case RG_VALUETYPE_NOT_DEFINED
:
1892 fprintf(stdout
, " Registry 2: key has no value\n");
1894 case RG_VALUETYPE_LONG
:
1895 case RG_VALUETYPE_STRING
:
1896 case RG_VALUETYPE_UNICODE
:
1898 RegValue value2
= rtl_allocateMemory(size2
);
1899 key2
.getValue(tmpName
, value2
);
1903 case RG_VALUETYPE_LONG
:
1904 fprintf(stdout
, " Registry 2: Value: Type = RG_VALUETYPE_LONG\n");
1906 stdout
, " Size = %lu\n",
1907 sal::static_int_cast
< unsigned long >(size2
));
1908 fprintf(stdout
, " Data = %p\n", value2
);
1910 case RG_VALUETYPE_STRING
:
1911 fprintf(stdout
, " Registry 2: Value: Type = RG_VALUETYPE_STRING\n");
1913 stdout
, " Size = %lu\n",
1914 sal::static_int_cast
< unsigned long >(size2
));
1915 fprintf(stdout
, " Data = \"%s\"\n", (sal_Char
*)value2
);
1917 case RG_VALUETYPE_UNICODE
:
1919 OUString
uStrValue((sal_Unicode
*)value2
);
1920 fprintf(stdout
, " Registry 2: Value: Type = RG_VALUETYPE_UNICODE\n");
1922 stdout
, " Size = %lu\n",
1923 sal::static_int_cast
< unsigned long >(size2
));
1924 fprintf(stdout
, " Data = \"%s\"\n", U2S(uStrValue
));
1932 rtl_freeMemory(value2
);
1935 case RG_VALUETYPE_BINARY
:
1936 fprintf(stdout
, " Registry 2: Value: Type = RG_VALUETYPE_BINARY\n");
1938 case RG_VALUETYPE_LONGLIST
:
1940 RegistryValueList
<sal_Int32
> valueList
;
1941 key2
.getLongListValue(tmpName
, valueList
);
1942 fprintf(stdout
, " Registry 2: Value: Type = RG_VALUETYPE_LONGLIST\n");
1944 stdout
, " Size = %lu\n",
1945 sal::static_int_cast
< unsigned long >(size2
));
1946 sal_uInt32 length
= valueList
.getLength();
1947 for (sal_uInt32 i
=0; i
<length
; i
++)
1950 stdout
, " Data[%lu] = %ld\n",
1951 sal::static_int_cast
< unsigned long >(i
),
1952 sal::static_int_cast
< long >(valueList
.getElement(i
)));
1956 case RG_VALUETYPE_STRINGLIST
:
1958 RegistryValueList
<sal_Char
*> valueList
;
1959 key2
.getStringListValue(tmpName
, valueList
);
1960 fprintf(stdout
, " Registry 2: Value: Type = RG_VALUETYPE_STRINGLIST\n");
1962 stdout
, " Size = %lu\n",
1963 sal::static_int_cast
< unsigned long >(size2
));
1964 sal_uInt32 length
= valueList
.getLength();
1965 for (sal_uInt32 i
=0; i
<length
; i
++)
1968 stdout
, " Data[%lu] = \"%s\"\n",
1969 sal::static_int_cast
< unsigned long >(i
),
1970 valueList
.getElement(i
));
1974 case RG_VALUETYPE_UNICODELIST
:
1976 RegistryValueList
<sal_Unicode
*> valueList
;
1977 key2
.getUnicodeListValue(tmpName
, valueList
);
1978 fprintf(stdout
, " Registry 2: Value: Type = RG_VALUETYPE_UNICODELIST\n");
1980 stdout
, " Size = %lu\n",
1981 sal::static_int_cast
< unsigned long >(size2
));
1982 sal_uInt32 length
= valueList
.getLength();
1984 for (sal_uInt32 i
=0; i
<length
; i
++)
1986 uStrValue
= OUString(valueList
.getElement(i
));
1988 stdout
, " Data[%lu] = \"%s\"\n",
1989 sal::static_int_cast
< unsigned long >(i
), U2S(uStrValue
));
1998 static bool hasPublishedChildren(RegistryKey
& key
) {
1999 RegistryKeyNames subKeyNames
;
2000 key
.getKeyNames(rtl::OUString(), subKeyNames
);
2001 for (sal_uInt32 i
= 0; i
< subKeyNames
.getLength(); ++i
) {
2002 rtl::OUString
keyName(subKeyNames
.getElement(i
));
2003 if (!options
.matchedWithExcludeKey(keyName
)) {
2004 keyName
= keyName
.copy(keyName
.lastIndexOf('/') + 1);
2006 if (!key
.openKey(keyName
, subKey
)) {
2007 if (options
.forceOutput()) {
2010 ("WARNING: could not open key \"%s\" in registry"
2012 U2S(subKeyNames
.getElement(i
)),
2013 options
.getRegName1().getStr());
2016 if (subKey
.isValid()) {
2019 if (subKey
.getValueInfo(rtl::OUString(), &type
, &size
)
2022 if (options
.forceOutput()) {
2025 ("WARNING: could not read key \"%s\" in registry"
2027 U2S(subKeyNames
.getElement(i
)),
2028 options
.getRegName1().getStr());
2030 } else if (type
== RG_VALUETYPE_BINARY
) {
2031 char * value
= new char[size
];
2032 bool published
= false;
2033 if (subKey
.getValue(rtl::OUString(), value
) != REG_NO_ERROR
)
2035 if (options
.forceOutput()) {
2038 ("WARNING: could not read key \"%s\" in"
2039 " registry \"%s\"\n"),
2040 U2S(subKeyNames
.getElement(i
)),
2041 options
.getRegName1().getStr());
2044 published
= typereg::Reader(
2045 value
, size
, false, TYPEREG_VERSION_1
).
2059 static sal_uInt32
checkDifferences(
2060 RegistryKey
& key
, StringSet
& keys
, RegistryKeyNames
& subKeyNames1
,
2061 RegistryKeyNames
& subKeyNames2
)
2063 sal_uInt32 nError
= 0;
2064 sal_uInt32 length1
= subKeyNames1
.getLength();
2065 sal_uInt32 length2
= subKeyNames2
.getLength();
2068 for (i
=0; i
<length1
; i
++)
2070 sal_Bool bFound
= sal_False
;
2071 for (j
=0; j
<length2
; j
++)
2073 if ( subKeyNames1
.getElement(i
) == subKeyNames2
.getElement(j
) )
2076 keys
.insert(subKeyNames1
.getElement(i
));
2082 if ( options
.fullCheck() )
2084 if ( options
.forceOutput() )
2086 fprintf(stdout
, "EXISTENCE: key \"%s\" exists only in registry \"%s\"\n",
2087 U2S(subKeyNames1
.getElement(i
)), options
.getRegName1().getStr());
2093 rtl::OUString
keyName(subKeyNames1
.getElement(i
));
2094 if (!options
.matchedWithExcludeKey(keyName
)) {
2095 keyName
= keyName
.copy(keyName
.lastIndexOf('/') + 1);
2097 if (key
.openKey(keyName
, subKey
)) {
2098 if (options
.forceOutput()) {
2101 ("ERROR: could not open key \"%s\" in registry"
2103 U2S(subKeyNames1
.getElement(i
)),
2104 options
.getRegName1().getStr());
2108 if (subKey
.isValid()) {
2111 if (subKey
.getValueInfo(rtl::OUString(), &type
, &size
)
2114 if (options
.forceOutput()) {
2117 ("ERROR: could not read key \"%s\" in"
2118 " registry \"%s\"\n"),
2119 U2S(subKeyNames1
.getElement(i
)),
2120 options
.getRegName1().getStr());
2123 } else if (type
== RG_VALUETYPE_BINARY
) {
2124 char * value
= new char[size
];
2125 if (subKey
.getValue(rtl::OUString(), value
)
2128 if (options
.forceOutput()) {
2131 ("ERROR: could not read key \"%s\" in"
2132 " registry \"%s\"\n"),
2133 U2S(subKeyNames1
.getElement(i
)),
2134 options
.getRegName1().getStr());
2138 typereg::Reader
reader(
2139 value
, size
, false, TYPEREG_VERSION_1
);
2140 if (reader
.getTypeClass() == RT_TYPE_MODULE
) {
2141 if (options
.checkUnpublished()
2142 || hasPublishedChildren(subKey
))
2144 if (options
.forceOutput()) {
2147 ("EXISTENCE: module \"%s\""
2148 " %sexists only in registry"
2150 U2S(subKeyNames1
.getElement(
2152 (options
.checkUnpublished()
2154 : "with published children "));
2158 } else if (options
.checkUnpublished()
2159 || reader
.isPublished())
2161 if (options
.forceOutput()) {
2164 ("EXISTENCE: %spublished key \"%s\""
2165 " exists only in registry 1\n"),
2166 reader
.isPublished() ? "" : "un",
2167 U2S(subKeyNames1
.getElement(i
)));
2180 for (i
=0; i
<length2
; i
++)
2182 sal_Bool bFound
= sal_False
;
2183 for (j
=0; j
<length1
; j
++)
2185 if ( subKeyNames2
.getElement(i
) == subKeyNames1
.getElement(j
) )
2188 keys
.insert(subKeyNames2
.getElement(i
));
2192 if ( !bFound
&& options
.fullCheck() )
2194 if ( options
.forceOutput() )
2196 fprintf(stdout
, "EXISTENCE: key \"%s\" exists only in registry \"%s\"\n",
2197 U2S(subKeyNames2
.getElement(i
)), options
.getRegName2().getStr());
2205 static sal_uInt32
compareKeys(RegistryKey
& key1
, RegistryKey
& key2
)
2207 sal_uInt32 nError
= 0;
2209 RegValueType valueType1
= RG_VALUETYPE_NOT_DEFINED
;
2210 RegValueType valueType2
= RG_VALUETYPE_NOT_DEFINED
;
2211 sal_uInt32 size1
= 0;
2212 sal_uInt32 size2
= 0;
2214 RegError e1
= key1
.getValueInfo(tmpName
, &valueType1
, &size1
);
2215 RegError e2
= key2
.getValueInfo(tmpName
, &valueType2
, &size2
);
2217 if ( e1
== e2
&& e1
!= REG_VALUE_NOT_EXISTS
&& e1
!= REG_INVALID_VALUE
)
2219 nError
+= checkValueDifference(key1
, valueType1
, size1
, key2
, valueType2
, size2
);
2222 if ( e1
!= REG_INVALID_VALUE
|| e2
!= REG_INVALID_VALUE
)
2224 if ( options
.forceOutput() )
2226 fprintf(stdout
, "VALUES: key values of key \"%s\" are different\n", U2S(key1
.getName()));
2232 RegistryKeyNames subKeyNames1
;
2233 RegistryKeyNames subKeyNames2
;
2235 key1
.getKeyNames(tmpName
, subKeyNames1
);
2236 key2
.getKeyNames(tmpName
, subKeyNames2
);
2239 nError
+= checkDifferences(key1
, keys
, subKeyNames1
, subKeyNames2
);
2241 StringSet::iterator iter
= keys
.begin();
2242 StringSet::iterator end
= keys
.end();
2244 RegistryKey subKey1
, subKey2
;
2246 while ( iter
!= end
)
2248 keyName
= OUString(*iter
);
2249 if ( options
.matchedWithExcludeKey(keyName
) )
2255 sal_Int32 nPos
= keyName
.lastIndexOf( '/' );
2256 keyName
= keyName
.copy( nPos
!= -1 ? nPos
+1 : 0 );
2257 if ( key1
.openKey(keyName
, subKey1
) )
2259 if ( options
.forceOutput() )
2261 fprintf(stdout
, "ERROR: could not open key \"%s\" in registry \"%s\"\n",
2262 U2S(*iter
), options
.getRegName1().getStr());
2266 if ( key2
.openKey(keyName
, subKey2
) )
2268 if ( options
.forceOutput() )
2270 fprintf(stdout
, "ERROR: could not open key \"%s\" in registry \"%s\"\n",
2271 U2S(*iter
), options
.getRegName2().getStr());
2275 if ( subKey1
.isValid() && subKey2
.isValid() )
2277 nError
+= compareKeys(subKey1
, subKey2
);
2287 #if (defined UNX) || (defined OS2) || defined __MINGW32__
2288 int main( int argc
, char * argv
[] )
2290 int _cdecl
main( int argc
, char * argv
[] )
2293 if ( !options
.initOptions(argc
, argv
) )
2298 OUString
regName1( convertToFileUrl(options
.getRegName1()) );
2299 OUString
regName2( convertToFileUrl(options
.getRegName2()) );
2304 if ( reg1
.open(regName1
, REG_READONLY
) )
2306 fprintf(stdout
, "%s: open registry \"%s\" failed\n",
2307 options
.getProgramName().getStr(), options
.getRegName1().getStr());
2310 if ( reg2
.open(regName2
, REG_READONLY
) )
2312 fprintf(stdout
, "%s: open registry \"%s\" failed\n",
2313 options
.getProgramName().getStr(), options
.getRegName2().getStr());
2317 RegistryKey key1
, key2
;
2318 if ( reg1
.openRootKey(key1
) )
2320 fprintf(stdout
, "%s: open root key of registry \"%s\" failed\n",
2321 options
.getProgramName().getStr(), options
.getRegName1().getStr());
2324 if ( reg2
.openRootKey(key2
) )
2326 fprintf(stdout
, "%s: open root key of registry \"%s\" failed\n",
2327 options
.getProgramName().getStr(), options
.getRegName2().getStr());
2330 if ( options
.isStartKeyValid() )
2332 if ( options
.matchedWithExcludeKey( S2U(options
.getStartKey()) ) )
2334 fprintf(stdout
, "%s: start key is equal to one of the exclude keys\n",
2335 options
.getProgramName().getStr());
2338 RegistryKey sk1
, sk2
;
2339 if ( key1
.openKey(S2U(options
.getStartKey()), sk1
) )
2341 fprintf(stdout
, "%s: open start key of registry \"%s\" failed\n",
2342 options
.getProgramName().getStr(), options
.getRegName1().getStr());
2345 if ( key2
.openKey(S2U(options
.getStartKey()), sk2
) )
2347 fprintf(stdout
, "%s: open start key of registry \"%s\" failed\n",
2348 options
.getProgramName().getStr(), options
.getRegName2().getStr());
2356 sal_uInt32 nError
= compareKeys(key1
, key2
);
2359 if ( options
.unoTypeCheck() )
2361 fprintf(stdout
, "%s: registries are incompatible: %lu differences!\n",
2362 options
.getProgramName().getStr(),
2363 sal::static_int_cast
< unsigned long >(nError
));
2366 fprintf(stdout
, "%s: registries contain %lu differences!\n",
2367 options
.getProgramName().getStr(),
2368 sal::static_int_cast
< unsigned long >(nError
));
2372 if ( options
.unoTypeCheck() )
2374 fprintf(stdout
, "%s: registries are compatible!\n",
2375 options
.getProgramName().getStr());
2378 fprintf(stdout
, "%s: registries are equal!\n",
2379 options
.getProgramName().getStr());
2387 fprintf(stdout
, "%s: closing registry \"%s\" failed\n",
2388 options
.getProgramName().getStr(), options
.getRegName1().getStr());
2393 fprintf(stdout
, "%s: closing registry \"%s\" failed\n",
2394 options
.getProgramName().getStr(), options
.getRegName2().getStr());
2398 return nError
> 0 ? 11 : 0;