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