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