LibreOffice Module registry (master) 1
reflread.cxx
Go to the documentation of this file.
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#include <sal/config.h>
21
22#include <cstring>
23#include <memory>
24#include <new>
25#include <vector>
26
27#include <sal/types.h>
28#include <osl/endian.h>
29#include <osl/diagnose.h>
30#include <sal/log.hxx>
31
32#include <registry/refltype.hxx>
34#include <registry/version.h>
35
36#include "reflcnst.hxx"
37
38#include <cstddef>
39
40const char NULL_STRING[1] = { 0 };
41const sal_Unicode NULL_WSTRING[1] = { 0 };
42
43const sal_uInt32 magic = 0x12345678;
44const sal_uInt16 minorVersion = 0x0000;
45const sal_uInt16 majorVersion = 0x0001;
46
47namespace {
48
52class BlopObject
53{
54public:
55 struct BoundsError {};
56
57 const sal_uInt8* m_pBuffer;
58 sal_uInt32 m_bufferLen;
59
60 BlopObject(const sal_uInt8* buffer, sal_uInt32 len);
61 // throws std::bad_alloc
62
63 sal_uInt8 readBYTE(sal_uInt32 index) const
64 {
65 if (index >= m_bufferLen) {
66 throw BoundsError();
67 }
68 return m_pBuffer[index];
69 }
70
71 sal_Int16 readINT16(sal_uInt32 index) const
72 {
73 if (m_bufferLen < 2 || index >= m_bufferLen - 1) {
74 throw BoundsError();
75 }
76 return ((m_pBuffer[index] << 8) | (m_pBuffer[index+1] << 0));
77 }
78
79 sal_uInt16 readUINT16(sal_uInt32 index) const
80 {
81 if (m_bufferLen < 2 || index >= m_bufferLen - 1) {
82 throw BoundsError();
83 }
84 return ((m_pBuffer[index] << 8) | (m_pBuffer[index+1] << 0));
85 }
86
87 sal_Int32 readINT32(sal_uInt32 index) const
88 {
89 if (m_bufferLen < 4 || index >= m_bufferLen - 3) {
90 throw BoundsError();
91 }
92 return (
93 (m_pBuffer[index] << 24) |
94 (m_pBuffer[index+1] << 16) |
95 (m_pBuffer[index+2] << 8) |
96 (m_pBuffer[index+3] << 0)
97 );
98 }
99
100 sal_uInt32 readUINT32(sal_uInt32 index) const
101 {
102 if (m_bufferLen < 4 || index >= m_bufferLen - 3) {
103 throw BoundsError();
104 }
105 return (
106 (m_pBuffer[index] << 24) |
107 (m_pBuffer[index+1] << 16) |
108 (m_pBuffer[index+2] << 8) |
109 (m_pBuffer[index+3] << 0)
110 );
111 }
112
113 sal_Int64 readINT64(sal_uInt32 index) const
114 {
115 if (m_bufferLen < 8 || index >= m_bufferLen - 7) {
116 throw BoundsError();
117 }
118 return (
119 (static_cast<sal_Int64>(m_pBuffer[index]) << 56) |
120 (static_cast<sal_Int64>(m_pBuffer[index+1]) << 48) |
121 (static_cast<sal_Int64>(m_pBuffer[index+2]) << 40) |
122 (static_cast<sal_Int64>(m_pBuffer[index+3]) << 32) |
123 (static_cast<sal_Int64>(m_pBuffer[index+4]) << 24) |
124 (static_cast<sal_Int64>(m_pBuffer[index+5]) << 16) |
125 (static_cast<sal_Int64>(m_pBuffer[index+6]) << 8) |
126 (static_cast<sal_Int64>(m_pBuffer[index+7]) << 0)
127 );
128 }
129
130 sal_uInt64 readUINT64(sal_uInt32 index) const
131 {
132 if (m_bufferLen < 8 || index >= m_bufferLen - 7) {
133 throw BoundsError();
134 }
135 return (
136 (static_cast<sal_uInt64>(m_pBuffer[index]) << 56) |
137 (static_cast<sal_uInt64>(m_pBuffer[index+1]) << 48) |
138 (static_cast<sal_uInt64>(m_pBuffer[index+2]) << 40) |
139 (static_cast<sal_uInt64>(m_pBuffer[index+3]) << 32) |
140 (static_cast<sal_uInt64>(m_pBuffer[index+4]) << 24) |
141 (static_cast<sal_uInt64>(m_pBuffer[index+5]) << 16) |
142 (static_cast<sal_uInt64>(m_pBuffer[index+6]) << 8) |
143 (static_cast<sal_uInt64>(m_pBuffer[index+7]) << 0)
144 );
145 }
146};
147
148}
149
150BlopObject::BlopObject(const sal_uInt8* buffer, sal_uInt32 len)
151 : m_bufferLen(len)
152{
153 m_pBuffer = buffer;
154}
155
156namespace {
157
158class StringCache
159{
160public:
161 std::vector<std::unique_ptr<sal_Unicode[]>> m_stringTable;
162 sal_uInt16 m_stringsCopied;
163
164 explicit StringCache(sal_uInt16 size); // throws std::bad_alloc
165
166 const sal_Unicode* getString(sal_uInt16 index) const;
167 sal_uInt16 createString(const sal_uInt8* buffer); // throws std::bad_alloc
168};
169
170}
171
172StringCache::StringCache(sal_uInt16 size)
173 : m_stringTable(size)
174 , m_stringsCopied(0)
175{
176}
177
178const sal_Unicode* StringCache::getString(sal_uInt16 index) const
179{
180 if ((index > 0) && (index <= m_stringsCopied))
181 return m_stringTable[index - 1].get();
182 else
183 return nullptr;
184}
185
186sal_uInt16 StringCache::createString(const sal_uInt8* buffer)
187{
188 if (m_stringsCopied < m_stringTable.size())
189 {
190 sal_uInt32 len = UINT16StringLen(buffer);
191
192 m_stringTable[m_stringsCopied].reset( new sal_Unicode[len + 1] );
193
194 readString(buffer, m_stringTable[m_stringsCopied].get(), (len + 1) * sizeof(sal_Unicode));
195
196 return ++m_stringsCopied;
197 }
198 else
199 return 0;
200}
201
202namespace {
203
204class ConstantPool : public BlopObject
205{
206public:
207
208 sal_uInt16 m_numOfEntries;
209 std::unique_ptr<sal_Int32[]> m_pIndex; // index values may be < 0 for cached string constants
210
211 std::unique_ptr<StringCache> m_pStringCache;
212
213 ConstantPool(const sal_uInt8* buffer, sal_uInt32 len, sal_uInt16 numEntries)
214 : BlopObject(buffer, len)
215 , m_numOfEntries(numEntries)
216 {
217 }
218
219 sal_uInt32 parseIndex(); // throws std::bad_alloc
220
221 CPInfoTag readTag(sal_uInt16 index) const;
222
223 const char* readUTF8NameConstant(sal_uInt16 index) const;
224 bool readBOOLConstant(sal_uInt16 index) const;
225 sal_Int8 readBYTEConstant(sal_uInt16 index) const;
226 sal_Int16 readINT16Constant(sal_uInt16 index) const;
227 sal_uInt16 readUINT16Constant(sal_uInt16 index) const;
228 sal_Int32 readINT32Constant(sal_uInt16 index) const;
229 sal_uInt32 readUINT32Constant(sal_uInt16 index) const;
230 sal_Int64 readINT64Constant(sal_uInt16 index) const;
231 sal_uInt64 readUINT64Constant(sal_uInt16 index) const;
232 float readFloatConstant(sal_uInt16 index) const;
233 double readDoubleConstant(sal_uInt16 index) const;
234 const sal_Unicode* readStringConstant(sal_uInt16 index) const;
235 // throws std::bad_alloc
236};
237
238}
239
240sal_uInt32 ConstantPool::parseIndex()
241{
242 m_pIndex.reset();
243 m_pStringCache.reset();
244
245 sal_uInt32 offset = 0;
246 sal_uInt16 numOfStrings = 0;
247
248 if (m_numOfEntries)
249 {
250 m_pIndex.reset( new sal_Int32[m_numOfEntries] );
251
252 for (int i = 0; i < m_numOfEntries; i++)
253 {
254 m_pIndex[i] = offset;
255
256 offset += readUINT32(offset);
257
258 if ( static_cast<CPInfoTag>(readUINT16(m_pIndex[i] + CP_OFFSET_ENTRY_TAG)) ==
260 {
261 numOfStrings++;
262 }
263
264 }
265 }
266
267 if (numOfStrings)
268 {
269 m_pStringCache.reset( new StringCache(numOfStrings) );
270 }
271
272 m_bufferLen = offset;
273
274 return offset;
275}
276
277CPInfoTag ConstantPool::readTag(sal_uInt16 index) const
278{
280
281 if (m_pIndex && (index > 0) && (index <= m_numOfEntries))
282 {
283 tag = static_cast<CPInfoTag>(readUINT16(m_pIndex[index - 1] + CP_OFFSET_ENTRY_TAG));
284 }
285
286 return tag;
287}
288
289const char* ConstantPool::readUTF8NameConstant(sal_uInt16 index) const
290{
291 const char* aName = NULL_STRING;
292
293 if (m_pIndex && (index > 0) && (index <= m_numOfEntries))
294 {
295 if (readUINT16(m_pIndex[index - 1] + CP_OFFSET_ENTRY_TAG) == CP_TAG_UTF8_NAME)
296 {
297 sal_uInt32 n = m_pIndex[index - 1] + CP_OFFSET_ENTRY_DATA;
298 if (n < m_bufferLen
299 && std::memchr(m_pBuffer + n, 0, m_bufferLen - n) != nullptr)
300 {
301 aName = reinterpret_cast<const char*>(m_pBuffer + n);
302 }
303 }
304 }
305
306 return aName;
307}
308
309bool ConstantPool::readBOOLConstant(sal_uInt16 index) const
310{
311 bool aBool = false;
312
313 if (m_pIndex && (index> 0) && (index <= m_numOfEntries))
314 {
315 if (readUINT16(m_pIndex[index - 1] + CP_OFFSET_ENTRY_TAG) == CP_TAG_CONST_BOOL)
316 {
317 aBool = readBYTE(m_pIndex[index - 1] + CP_OFFSET_ENTRY_DATA) != 0;
318 }
319 }
320
321 return aBool;
322}
323
324sal_Int8 ConstantPool::readBYTEConstant(sal_uInt16 index) const
325{
326 sal_Int8 aByte = 0;
327
328 if (m_pIndex && (index> 0) && (index <= m_numOfEntries))
329 {
330 if (readUINT16(m_pIndex[index - 1] + CP_OFFSET_ENTRY_TAG) == CP_TAG_CONST_BYTE)
331 {
332 aByte = static_cast< sal_Int8 >(
333 readBYTE(m_pIndex[index - 1] + CP_OFFSET_ENTRY_DATA));
334 }
335 }
336
337 return aByte;
338}
339
340sal_Int16 ConstantPool::readINT16Constant(sal_uInt16 index) const
341{
342 sal_Int16 aINT16 = 0;
343
344 if (m_pIndex && (index> 0) && (index <= m_numOfEntries))
345 {
346 if (readUINT16(m_pIndex[index - 1] + CP_OFFSET_ENTRY_TAG) == CP_TAG_CONST_INT16)
347 {
348 aINT16 = readINT16(m_pIndex[index - 1] + CP_OFFSET_ENTRY_DATA);
349 }
350 }
351
352 return aINT16;
353}
354
355sal_uInt16 ConstantPool::readUINT16Constant(sal_uInt16 index) const
356{
357 sal_uInt16 asal_uInt16 = 0;
358
359 if (m_pIndex && (index> 0) && (index <= m_numOfEntries))
360 {
361 if (readUINT16(m_pIndex[index - 1] + CP_OFFSET_ENTRY_TAG) == CP_TAG_CONST_UINT16)
362 {
363 asal_uInt16 = readUINT16(m_pIndex[index - 1] + CP_OFFSET_ENTRY_DATA);
364 }
365 }
366
367 return asal_uInt16;
368}
369
370sal_Int32 ConstantPool::readINT32Constant(sal_uInt16 index) const
371{
372 sal_Int32 aINT32 = 0;
373
374 if (m_pIndex && (index> 0) && (index <= m_numOfEntries))
375 {
376 if (readUINT16(m_pIndex[index - 1] + CP_OFFSET_ENTRY_TAG) == CP_TAG_CONST_INT32)
377 {
378 aINT32 = readINT32(m_pIndex[index - 1] + CP_OFFSET_ENTRY_DATA);
379 }
380 }
381
382 return aINT32;
383}
384
385sal_uInt32 ConstantPool::readUINT32Constant(sal_uInt16 index) const
386{
387 sal_uInt32 aUINT32 = 0;
388
389 if (m_pIndex && (index> 0) && (index <= m_numOfEntries))
390 {
391 if (readUINT16(m_pIndex[index - 1] + CP_OFFSET_ENTRY_TAG) == CP_TAG_CONST_UINT32)
392 {
393 aUINT32 = readUINT32(m_pIndex[index - 1] + CP_OFFSET_ENTRY_DATA);
394 }
395 }
396
397 return aUINT32;
398}
399
400sal_Int64 ConstantPool::readINT64Constant(sal_uInt16 index) const
401{
402 sal_Int64 aINT64 = 0;
403
404 if (m_pIndex && (index> 0) && (index <= m_numOfEntries))
405 {
406 if (readUINT16(m_pIndex[index - 1] + CP_OFFSET_ENTRY_TAG) == CP_TAG_CONST_INT64)
407 {
408 aINT64 = readINT64(m_pIndex[index - 1] + CP_OFFSET_ENTRY_DATA);
409 }
410 }
411
412 return aINT64;
413}
414
415sal_uInt64 ConstantPool::readUINT64Constant(sal_uInt16 index) const
416{
417 sal_uInt64 aUINT64 = 0;
418
419 if (m_pIndex && (index> 0) && (index <= m_numOfEntries))
420 {
421 if (readUINT16(m_pIndex[index - 1] + CP_OFFSET_ENTRY_TAG) == CP_TAG_CONST_UINT64)
422 {
423 aUINT64 = readUINT64(m_pIndex[index - 1] + CP_OFFSET_ENTRY_DATA);
424 }
425 }
426
427 return aUINT64;
428}
429
430float ConstantPool::readFloatConstant(sal_uInt16 index) const
431{
432 union
433 {
434 float v;
435 sal_uInt32 b;
436 } x = { 0.0f };
437
438 if (m_pIndex && (index> 0) && (index <= m_numOfEntries))
439 {
440 if (readUINT16(m_pIndex[index - 1] + CP_OFFSET_ENTRY_TAG) == CP_TAG_CONST_FLOAT)
441 {
442#ifdef REGTYPE_IEEE_NATIVE
443 x.b = readUINT32(m_pIndex[index - 1] + CP_OFFSET_ENTRY_DATA);
444#else
445# error no IEEE
446#endif
447 }
448 }
449
450 return x.v;
451}
452
453double ConstantPool::readDoubleConstant(sal_uInt16 index) const
454{
455 union
456 {
457 double v;
458 struct
459 {
460 sal_uInt32 b1;
461 sal_uInt32 b2;
462 } b;
463 } x = { 0.0 };
464
465 if (m_pIndex && (index> 0) && (index <= m_numOfEntries))
466 {
467 if (readUINT16(m_pIndex[index - 1] + CP_OFFSET_ENTRY_TAG) == CP_TAG_CONST_DOUBLE)
468 {
469
470#ifdef REGTYPE_IEEE_NATIVE
471# ifdef OSL_BIGENDIAN
472 x.b.b1 = readUINT32(m_pIndex[index - 1] + CP_OFFSET_ENTRY_DATA);
473 x.b.b2 = readUINT32(m_pIndex[index - 1] + CP_OFFSET_ENTRY_DATA + sizeof(sal_uInt32));
474# else
475 x.b.b1 = readUINT32(m_pIndex[index - 1] + CP_OFFSET_ENTRY_DATA + sizeof(sal_uInt32));
476 x.b.b2 = readUINT32(m_pIndex[index - 1] + CP_OFFSET_ENTRY_DATA);
477# endif
478#else
479# error no IEEE
480#endif
481 }
482 }
483
484 return x.v;
485}
486
487const sal_Unicode* ConstantPool::readStringConstant(sal_uInt16 index) const
488{
489 const sal_Unicode* aString = NULL_WSTRING;
490
491 if (m_pIndex && (index> 0) && (index <= m_numOfEntries) && m_pStringCache)
492 {
493 if (m_pIndex[index - 1] >= 0)
494 {
495 // create cached string now
496
497 if (readUINT16(m_pIndex[index - 1] + CP_OFFSET_ENTRY_TAG) == CP_TAG_CONST_STRING)
498 {
499 sal_uInt32 n = m_pIndex[index - 1] + CP_OFFSET_ENTRY_DATA;
500 if (n >= m_bufferLen
501 || (std::memchr(m_pBuffer + n, 0, m_bufferLen - n)
502 == nullptr))
503 {
504 throw BoundsError();
505 }
506 m_pIndex[index - 1] = -1 * m_pStringCache->createString(m_pBuffer + n);
507 }
508 }
509
510 aString = m_pStringCache->getString(static_cast<sal_uInt16>(m_pIndex[index - 1] * -1));
511 }
512
513 return aString;
514}
515
516namespace {
517
518class FieldList : public BlopObject
519{
520public:
521
522 sal_uInt16 m_numOfEntries;
523 size_t m_FIELD_ENTRY_SIZE;
524 ConstantPool* m_pCP;
525
526 FieldList(const sal_uInt8* buffer, sal_uInt32 len, sal_uInt16 numEntries, ConstantPool* pCP)
527 : BlopObject(buffer, len)
528 , m_numOfEntries(numEntries)
529 , m_pCP(pCP)
530 {
531 if ( m_numOfEntries > 0 )
532 {
533 sal_uInt16 numOfFieldEntries = readUINT16(0);
534 m_FIELD_ENTRY_SIZE = numOfFieldEntries * sizeof(sal_uInt16);
535 } else
536 {
537 m_FIELD_ENTRY_SIZE = 0;
538 }
539 }
540
541 sal_uInt32 parseIndex() const { return ((m_numOfEntries ? sizeof(sal_uInt16) : 0) + (m_numOfEntries * m_FIELD_ENTRY_SIZE));}
542
543 const char* getFieldName(sal_uInt16 index) const;
544 const char* getFieldType(sal_uInt16 index) const;
545 RTFieldAccess getFieldAccess(sal_uInt16 index) const;
546 RTValueType getFieldConstValue(sal_uInt16 index, RTConstValueUnion* value) const;
547 // throws std::bad_alloc
548 const char* getFieldDoku(sal_uInt16 index) const;
549 const char* getFieldFileName(sal_uInt16 index) const;
550};
551
552}
553
554const char* FieldList::getFieldName(sal_uInt16 index) const
555{
556 const char* aName = nullptr;
557
558 if ((m_numOfEntries > 0) && (index <= m_numOfEntries))
559 {
560 try {
561 aName = m_pCP->readUTF8NameConstant(readUINT16(sizeof(sal_uInt16) + (index * m_FIELD_ENTRY_SIZE) + FIELD_OFFSET_NAME));
562 } catch (BlopObject::BoundsError &) {
563 SAL_WARN("registry", "bad data");
564 }
565 }
566
567 return aName;
568}
569
570const char* FieldList::getFieldType(sal_uInt16 index) const
571{
572 const char* aName = nullptr;
573
574 if ((m_numOfEntries > 0) && (index <= m_numOfEntries))
575 {
576 try {
577 aName = m_pCP->readUTF8NameConstant(readUINT16(sizeof(sal_uInt16) + (index * m_FIELD_ENTRY_SIZE) + FIELD_OFFSET_TYPE));
578 } catch (BlopObject::BoundsError &) {
579 SAL_WARN("registry", "bad data");
580 }
581 }
582
583 return aName;
584}
585
586RTFieldAccess FieldList::getFieldAccess(sal_uInt16 index) const
587{
589
590 if ((m_numOfEntries > 0) && (index <= m_numOfEntries))
591 {
592 try {
593 aAccess = static_cast<RTFieldAccess>(readUINT16(sizeof(sal_uInt16) + (index * m_FIELD_ENTRY_SIZE) + FIELD_OFFSET_ACCESS));
594 } catch (BlopObject::BoundsError &) {
595 SAL_WARN("registry", "bad data");
596 }
597 }
598
599 return aAccess;
600}
601
602RTValueType FieldList::getFieldConstValue(sal_uInt16 index, RTConstValueUnion* value) const
603{
605 try {
606 if ((m_numOfEntries > 0) && (index <= m_numOfEntries))
607 {
608 sal_uInt16 cpIndex = readUINT16(sizeof(sal_uInt16) + (index * m_FIELD_ENTRY_SIZE) + FIELD_OFFSET_VALUE);
609 switch (m_pCP->readTag(cpIndex))
610 {
612 value->aBool = m_pCP->readBOOLConstant(cpIndex);
613 ret = RT_TYPE_BOOL;
614 break;
616 value->aByte = m_pCP->readBYTEConstant(cpIndex);
617 ret = RT_TYPE_BYTE;
618 break;
620 value->aShort = m_pCP->readINT16Constant(cpIndex);
621 ret = RT_TYPE_INT16;
622 break;
624 value->aUShort = m_pCP->readUINT16Constant(cpIndex);
625 ret = RT_TYPE_UINT16;
626 break;
628 value->aLong = m_pCP->readINT32Constant(cpIndex);
629 ret = RT_TYPE_INT32;
630 break;
632 value->aULong = m_pCP->readUINT32Constant(cpIndex);
633 ret = RT_TYPE_UINT32;
634 break;
636 value->aHyper = m_pCP->readINT64Constant(cpIndex);
637 ret = RT_TYPE_INT64;
638 break;
640 value->aUHyper = m_pCP->readUINT64Constant(cpIndex);
641 ret = RT_TYPE_UINT64;
642 break;
644 value->aFloat = m_pCP->readFloatConstant(cpIndex);
645 ret = RT_TYPE_FLOAT;
646 break;
648 value->aDouble = m_pCP->readDoubleConstant(cpIndex);
649 ret = RT_TYPE_DOUBLE;
650 break;
652 value->aString = m_pCP->readStringConstant(cpIndex);
653 ret = RT_TYPE_STRING;
654 break;
655 default:
656 break;
657 }
658 }
659 } catch (BlopObject::BoundsError &) {
660 SAL_WARN("registry", "bad data");
661 }
662 return ret;
663}
664
665const char* FieldList::getFieldDoku(sal_uInt16 index) const
666{
667 const char* aDoku = nullptr;
668
669 if ((m_numOfEntries > 0) && (index <= m_numOfEntries))
670 {
671 try {
672 aDoku = m_pCP->readUTF8NameConstant(readUINT16(sizeof(sal_uInt16) + (index * m_FIELD_ENTRY_SIZE) + FIELD_OFFSET_DOKU));
673 } catch (BlopObject::BoundsError &) {
674 SAL_WARN("registry", "bad data");
675 }
676 }
677
678 return aDoku;
679}
680
681const char* FieldList::getFieldFileName(sal_uInt16 index) const
682{
683 const char* aFileName = nullptr;
684
685 if ((m_numOfEntries > 0) && (index <= m_numOfEntries))
686 {
687 try {
688 aFileName = m_pCP->readUTF8NameConstant(readUINT16(sizeof(sal_uInt16) + (index * m_FIELD_ENTRY_SIZE) + FIELD_OFFSET_FILENAME));
689 } catch (BlopObject::BoundsError &) {
690 SAL_WARN("registry", "bad data");
691 }
692 }
693
694 return aFileName;
695}
696
697namespace {
698
699class ReferenceList : public BlopObject
700{
701public:
702
703 sal_uInt16 m_numOfEntries;
704 size_t m_REFERENCE_ENTRY_SIZE;
705 ConstantPool* m_pCP;
706
707 ReferenceList(const sal_uInt8* buffer, sal_uInt32 len, sal_uInt16 numEntries, ConstantPool* pCP)
708 : BlopObject(buffer, len)
709 , m_numOfEntries(numEntries)
710 , m_pCP(pCP)
711 {
712 if ( m_numOfEntries > 0 )
713 {
714 sal_uInt16 numOfReferenceEntries = readUINT16(0);
715 m_REFERENCE_ENTRY_SIZE = numOfReferenceEntries * sizeof(sal_uInt16);
716 } else
717 {
718 m_REFERENCE_ENTRY_SIZE = 0;
719 }
720 }
721
722 const char* getReferenceName(sal_uInt16 index) const;
723 RTReferenceType getReferenceType(sal_uInt16 index) const;
724 const char* getReferenceDoku(sal_uInt16 index) const;
725 RTFieldAccess getReferenceAccess(sal_uInt16 index) const;
726};
727
728}
729
730const char* ReferenceList::getReferenceName(sal_uInt16 index) const
731{
732 const char* aName = nullptr;
733
734 if ((m_numOfEntries > 0) && (index <= m_numOfEntries))
735 {
736 try {
737 aName = m_pCP->readUTF8NameConstant(readUINT16(sizeof(sal_uInt16) + (index * m_REFERENCE_ENTRY_SIZE) + REFERENCE_OFFSET_NAME));
738 } catch (BlopObject::BoundsError &) {
739 SAL_WARN("registry", "bad data");
740 }
741 }
742
743 return aName;
744}
745
746RTReferenceType ReferenceList::getReferenceType(sal_uInt16 index) const
747{
749
750 if ((m_numOfEntries > 0) && (index <= m_numOfEntries))
751 {
752 try {
753 refType = static_cast<RTReferenceType>(readUINT16(sizeof(sal_uInt16) + (index * m_REFERENCE_ENTRY_SIZE) + REFERENCE_OFFSET_TYPE));
754 } catch (BlopObject::BoundsError &) {
755 SAL_WARN("registry", "bad data");
756 }
757 }
758
759 return refType;
760}
761
762const char* ReferenceList::getReferenceDoku(sal_uInt16 index) const
763{
764 const char* aDoku = nullptr;
765
766 if ((m_numOfEntries > 0) && (index <= m_numOfEntries))
767 {
768 try {
769 aDoku = m_pCP->readUTF8NameConstant(readUINT16(sizeof(sal_uInt16) + (index * m_REFERENCE_ENTRY_SIZE) + REFERENCE_OFFSET_DOKU));
770 } catch (BlopObject::BoundsError &) {
771 SAL_WARN("registry", "bad data");
772 }
773 }
774
775 return aDoku;
776}
777
778RTFieldAccess ReferenceList::getReferenceAccess(sal_uInt16 index) const
779{
781
782 if ((m_numOfEntries > 0) && (index <= m_numOfEntries))
783 {
784 try {
785 aAccess = static_cast<RTFieldAccess>(readUINT16(sizeof(sal_uInt16) + (index * m_REFERENCE_ENTRY_SIZE) + REFERENCE_OFFSET_ACCESS));
786 } catch (BlopObject::BoundsError &) {
787 SAL_WARN("registry", "bad data");
788 }
789 }
790
791 return aAccess;
792}
793
794namespace {
795
796class MethodList : public BlopObject
797{
798public:
799
800 sal_uInt16 m_numOfEntries;
801 size_t m_PARAM_ENTRY_SIZE;
802 std::unique_ptr<sal_uInt32[]> m_pIndex;
803 ConstantPool* m_pCP;
804
805 MethodList(const sal_uInt8* buffer, sal_uInt32 len, sal_uInt16 numEntries, ConstantPool* pCP)
806 : BlopObject(buffer, len)
807 , m_numOfEntries(numEntries)
808 , m_pCP(pCP)
809 {
810 if ( m_numOfEntries > 0 )
811 {
812 readUINT16(0) /* numOfMethodEntries */;
813 sal_uInt16 numOfParamEntries = readUINT16(sizeof(sal_uInt16));
814 m_PARAM_ENTRY_SIZE = numOfParamEntries * sizeof(sal_uInt16);
815 } else
816 {
817 m_PARAM_ENTRY_SIZE = 0;
818 }
819 }
820
821 sal_uInt32 parseIndex(); // throws std::bad_alloc
822
823 const char* getMethodName(sal_uInt16 index) const;
824 sal_uInt16 getMethodParamCount(sal_uInt16 index) const;
825 const char* getMethodParamType(sal_uInt16 index, sal_uInt16 paramIndex) const;
826 const char* getMethodParamName(sal_uInt16 index, sal_uInt16 paramIndex) const;
827 RTParamMode getMethodParamMode(sal_uInt16 index, sal_uInt16 paramIndex) const;
828 sal_uInt16 getMethodExcCount(sal_uInt16 index) const;
829 const char* getMethodExcType(sal_uInt16 index, sal_uInt16 excIndex) const;
830 const char* getMethodReturnType(sal_uInt16 index) const;
831 RTMethodMode getMethodMode(sal_uInt16 index) const;
832 const char* getMethodDoku(sal_uInt16 index) const;
833
834private:
835 sal_uInt16 calcMethodParamIndex( const sal_uInt16 index ) const;
836};
837
838}
839
840sal_uInt16 MethodList::calcMethodParamIndex( const sal_uInt16 index ) const
841{
842 return (METHOD_OFFSET_PARAM_COUNT + sizeof(sal_uInt16) + (index * m_PARAM_ENTRY_SIZE));
843}
844
845sal_uInt32 MethodList::parseIndex()
846{
847 m_pIndex.reset();
848
849 sal_uInt32 offset = 0;
850
851 if (m_numOfEntries)
852 {
853 offset = 2 * sizeof(sal_uInt16);
854 m_pIndex.reset( new sal_uInt32[m_numOfEntries] );
855
856 for (int i = 0; i < m_numOfEntries; i++)
857 {
858 m_pIndex[i] = offset;
859
860 offset += readUINT16(offset);
861 }
862 }
863
864 return offset;
865}
866
867const char* MethodList::getMethodName(sal_uInt16 index) const
868{
869 const char* aName = nullptr;
870
871 if ((m_numOfEntries > 0) && (index <= m_numOfEntries))
872 {
873 try {
874 aName = m_pCP->readUTF8NameConstant(readUINT16(m_pIndex[index] + METHOD_OFFSET_NAME));
875 } catch (BlopObject::BoundsError &) {
876 SAL_WARN("registry", "bad data");
877 }
878 }
879
880 return aName;
881}
882
883sal_uInt16 MethodList::getMethodParamCount(sal_uInt16 index) const
884{
885 sal_uInt16 aCount = 0;
886
887 if ((m_numOfEntries > 0) && (index <= m_numOfEntries))
888 {
889 try {
890 aCount = readUINT16(m_pIndex[index] + METHOD_OFFSET_PARAM_COUNT);
891 } catch (BlopObject::BoundsError &) {
892 SAL_WARN("registry", "bad data");
893 }
894 }
895
896 return aCount;
897}
898
899const char* MethodList::getMethodParamType(sal_uInt16 index, sal_uInt16 paramIndex) const
900{
901 const char* aName = nullptr;
902 try {
903 if ((m_numOfEntries > 0) &&
904 (index <= m_numOfEntries) &&
905 (paramIndex <= readUINT16(m_pIndex[index] + METHOD_OFFSET_PARAM_COUNT)))
906 {
907 aName = m_pCP->readUTF8NameConstant(
909 m_pIndex[index] +
910 calcMethodParamIndex(paramIndex) +
912 }
913 } catch (BlopObject::BoundsError &) {
914 SAL_WARN("registry", "bad data");
915 }
916 return aName;
917}
918
919const char* MethodList::getMethodParamName(sal_uInt16 index, sal_uInt16 paramIndex) const
920{
921 const char* aName = nullptr;
922 try {
923 if ((m_numOfEntries > 0) &&
924 (index <= m_numOfEntries) &&
925 (paramIndex <= readUINT16(m_pIndex[index] + METHOD_OFFSET_PARAM_COUNT)))
926 {
927 aName = m_pCP->readUTF8NameConstant(
929 m_pIndex[index] +
930 calcMethodParamIndex(paramIndex) +
932 }
933 } catch (BlopObject::BoundsError &) {
934 SAL_WARN("registry", "bad data");
935 }
936 return aName;
937}
938
939RTParamMode MethodList::getMethodParamMode(sal_uInt16 index, sal_uInt16 paramIndex) const
940{
942 try {
943 if ((m_numOfEntries > 0) &&
944 (index <= m_numOfEntries) &&
945 (paramIndex <= readUINT16(m_pIndex[index] + METHOD_OFFSET_PARAM_COUNT)))
946 {
947 aMode = static_cast<RTParamMode>(readUINT16(
948 m_pIndex[index] +
949 calcMethodParamIndex(paramIndex) +
951 }
952 } catch (BlopObject::BoundsError &) {
953 SAL_WARN("registry", "bad data");
954 }
955 return aMode;
956}
957
958#if defined(__COVERITY__)
959extern "C" void __coverity_tainted_data_sanitize__(void *);
960#endif
961
962sal_uInt16 MethodList::getMethodExcCount(sal_uInt16 index) const
963{
964 sal_uInt16 aCount = 0;
965
966 if ((m_numOfEntries > 0) && (index <= m_numOfEntries))
967 {
968 try {
969 aCount = readUINT16(m_pIndex[index] + calcMethodParamIndex(readUINT16(m_pIndex[index] + METHOD_OFFSET_PARAM_COUNT)));
970#if defined(__COVERITY__)
971 __coverity_tainted_data_sanitize__(&aCount);
972#endif
973 } catch (BlopObject::BoundsError &) {
974 SAL_WARN("registry", "bad data");
975 }
976 }
977
978 return aCount;
979}
980
981const char* MethodList::getMethodExcType(sal_uInt16 index, sal_uInt16 excIndex) const
982{
983 const char* aName = nullptr;
984
985 if ((m_numOfEntries > 0) && (index <= m_numOfEntries))
986 {
987 try {
988 sal_uInt32 excOffset = m_pIndex[index] + calcMethodParamIndex(readUINT16(m_pIndex[index] + METHOD_OFFSET_PARAM_COUNT));
989 if (excIndex <= readUINT16(excOffset))
990 {
991 aName = m_pCP->readUTF8NameConstant(
993 excOffset +
994 sizeof(sal_uInt16) +
995 (excIndex * sizeof(sal_uInt16))));
996 }
997 } catch (BlopObject::BoundsError &) {
998 SAL_WARN("registry", "bad data");
999 }
1000 }
1001
1002 return aName;
1003}
1004
1005const char* MethodList::getMethodReturnType(sal_uInt16 index) const
1006{
1007 const char* aName = nullptr;
1008
1009 if ((m_numOfEntries > 0) && (index <= m_numOfEntries))
1010 {
1011 try {
1012 aName = m_pCP->readUTF8NameConstant(readUINT16(m_pIndex[index] + METHOD_OFFSET_RETURN));
1013 } catch (BlopObject::BoundsError &) {
1014 SAL_WARN("registry", "bad data");
1015 }
1016 }
1017
1018 return aName;
1019}
1020
1021RTMethodMode MethodList::getMethodMode(sal_uInt16 index) const
1022{
1024
1025 if ((m_numOfEntries > 0) && (index <= m_numOfEntries))
1026 {
1027 try {
1028 aMode = static_cast<RTMethodMode>(readUINT16(m_pIndex[index] + METHOD_OFFSET_MODE));
1029 } catch (BlopObject::BoundsError &) {
1030 SAL_WARN("registry", "bad data");
1031 }
1032 }
1033
1034 return aMode;
1035}
1036
1037const char* MethodList::getMethodDoku(sal_uInt16 index) const
1038{
1039 const char* aDoku = nullptr;
1040
1041 if ((m_numOfEntries > 0) && (index <= m_numOfEntries))
1042 {
1043 try {
1044 aDoku = m_pCP->readUTF8NameConstant(readUINT16(m_pIndex[index] + METHOD_OFFSET_DOKU));
1045 } catch (BlopObject::BoundsError &) {
1046 SAL_WARN("registry", "bad data");
1047 }
1048 }
1049
1050 return aDoku;
1051}
1052
1053namespace {
1054
1055class TypeRegistryEntry: public BlopObject {
1056public:
1057 std::unique_ptr<ConstantPool> m_pCP;
1058 std::unique_ptr<FieldList> m_pFields;
1059 std::unique_ptr<MethodList> m_pMethods;
1060 std::unique_ptr<ReferenceList> m_pReferences;
1061 sal_uInt32 m_refCount;
1062 sal_uInt16 m_nSuperTypes;
1063 sal_uInt32 m_offset_SUPERTYPES;
1064
1065 TypeRegistryEntry(
1066 const sal_uInt8* buffer, sal_uInt32 len);
1067 // throws std::bad_alloc
1068
1069 typereg_Version getVersion() const;
1070};
1071
1072}
1073
1074TypeRegistryEntry::TypeRegistryEntry(
1075 const sal_uInt8* buffer, sal_uInt32 len):
1076 BlopObject(buffer, len), m_refCount(1), m_nSuperTypes(0),
1077 m_offset_SUPERTYPES(0)
1078{
1079 std::size_t const entrySize = sizeof(sal_uInt16);
1080 sal_uInt16 nHeaderEntries = readUINT16(OFFSET_N_ENTRIES);
1081 sal_uInt32 offset_N_SUPERTYPES = OFFSET_N_ENTRIES + entrySize + (nHeaderEntries * entrySize); // cannot overflow
1082 m_offset_SUPERTYPES = offset_N_SUPERTYPES + entrySize; // cannot overflow
1083 m_nSuperTypes = readUINT16(offset_N_SUPERTYPES);
1084
1085 sal_uInt32 offset_CP_SIZE = m_offset_SUPERTYPES + (m_nSuperTypes * entrySize); // cannot overflow
1086 sal_uInt32 offset_CP = offset_CP_SIZE + entrySize; // cannot overflow
1087
1088 if (offset_CP > m_bufferLen) {
1089 throw BoundsError();
1090 }
1091 m_pCP.reset(
1092 new ConstantPool(
1093 m_pBuffer + offset_CP, m_bufferLen - offset_CP,
1094 readUINT16(offset_CP_SIZE)));
1095
1096 sal_uInt32 offset = offset_CP + m_pCP->parseIndex(); //TODO: overflow
1097
1098 assert(m_bufferLen >= entrySize);
1099 if (offset > m_bufferLen - entrySize) {
1100 throw BoundsError();
1101 }
1102 m_pFields.reset(
1103 new FieldList(
1104 m_pBuffer + offset + entrySize, m_bufferLen - (offset + entrySize),
1105 readUINT16(offset), m_pCP.get()));
1106
1107 offset += sizeof(sal_uInt16) + m_pFields->parseIndex(); //TODO: overflow
1108
1109 assert(m_bufferLen >= entrySize);
1110 if (offset > m_bufferLen - entrySize) {
1111 throw BoundsError();
1112 }
1113 m_pMethods.reset(
1114 new MethodList(
1115 m_pBuffer + offset + entrySize, m_bufferLen - (offset + entrySize),
1116 readUINT16(offset), m_pCP.get()));
1117
1118 offset += sizeof(sal_uInt16) + m_pMethods->parseIndex(); //TODO: overflow
1119
1120 assert(m_bufferLen >= entrySize);
1121 if (offset > m_bufferLen - entrySize) {
1122 throw BoundsError();
1123 }
1124 m_pReferences.reset(
1125 new ReferenceList(
1126 m_pBuffer + offset + entrySize, m_bufferLen - (offset + entrySize),
1127 readUINT16(offset), m_pCP.get()));
1128}
1129
1130typereg_Version TypeRegistryEntry::getVersion() const {
1131 // Assumes two's complement arithmetic with modulo-semantics:
1132 return static_cast< typereg_Version >(readUINT32(OFFSET_MAGIC) - magic);
1133}
1134
1136 void const * buffer, sal_uInt32 length,
1137 void ** result)
1138{
1139 if (length < OFFSET_CP || length > SAL_MAX_UINT32) {
1140 *result = nullptr;
1141 return true;
1142 }
1143 std::unique_ptr< TypeRegistryEntry > entry;
1144 try {
1145 try {
1146 entry.reset(
1147 new TypeRegistryEntry(
1148 static_cast< sal_uInt8 const * >(buffer), length));
1149 } catch (std::bad_alloc &) {
1150 return false;
1151 }
1152 if (entry->readUINT32(OFFSET_SIZE) != length) {
1153 *result = nullptr;
1154 return true;
1155 }
1156 typereg_Version version = entry->getVersion();
1157 if (version < TYPEREG_VERSION_0 || version > TYPEREG_VERSION_1) {
1158 *result = nullptr;
1159 return true;
1160 }
1161 *result = entry.release();
1162 return true;
1163 } catch (BlopObject::BoundsError &) {
1164 SAL_WARN("registry", "bad data");
1165 return false;
1166 }
1167}
1168
1170{
1171 TypeRegistryEntry* pEntry = static_cast<TypeRegistryEntry*>(hEntry);
1172
1173 if (pEntry != nullptr)
1174 pEntry->m_refCount++;
1175}
1176
1178{
1179 TypeRegistryEntry* pEntry = static_cast<TypeRegistryEntry*>(hEntry);
1180
1181 if (pEntry != nullptr)
1182 {
1183 if (--pEntry->m_refCount == 0)
1184 delete pEntry;
1185 }
1186}
1187
1189 if (handle != nullptr) {
1190 try {
1191 return static_cast< TypeRegistryEntry const * >(handle)->getVersion();
1192 } catch (BlopObject::BoundsError &) {
1193 SAL_WARN("registry", "bad data");
1194 }
1195 }
1196 return TYPEREG_VERSION_0;
1197}
1198
1200{
1201 TypeRegistryEntry* pEntry = static_cast<TypeRegistryEntry*>(hEntry);
1202 if (pEntry != nullptr) {
1203 try {
1204 return static_cast<RTTypeClass>(pEntry->readUINT16(OFFSET_TYPE_CLASS) & ~RT_TYPE_PUBLISHED);
1205 } catch (BlopObject::BoundsError &) {
1206 SAL_WARN("registry", "bad data");
1207 }
1208 }
1209 return RT_TYPE_INVALID;
1210}
1211
1213{
1214 TypeRegistryEntry * entry = static_cast< TypeRegistryEntry * >(hEntry);
1215 if (entry != nullptr) {
1216 try {
1217 return (entry->readUINT16(OFFSET_TYPE_CLASS) & RT_TYPE_PUBLISHED) != 0;
1218 } catch (BlopObject::BoundsError &) {
1219 SAL_WARN("registry", "bad data");
1220 }
1221 }
1222 return false;
1223}
1224
1225void TYPEREG_CALLTYPE typereg_reader_getTypeName(void * hEntry, rtl_uString** pTypeName)
1226{
1227 TypeRegistryEntry* pEntry = static_cast<TypeRegistryEntry*>(hEntry);
1228 if (pEntry != nullptr) {
1229 try {
1230 const char* pTmp = pEntry->m_pCP->readUTF8NameConstant(pEntry->readUINT16(OFFSET_THIS_TYPE));
1231 rtl_string2UString(
1232 pTypeName, pTmp, pTmp == nullptr ? 0 : rtl_str_getLength(pTmp),
1233 RTL_TEXTENCODING_UTF8, OSTRING_TO_OUSTRING_CVTFLAGS);
1234 return;
1235 } catch (BlopObject::BoundsError &) {
1236 SAL_WARN("registry", "bad data");
1237 }
1238 }
1239 rtl_uString_new(pTypeName);
1240}
1241
1242
1243void TYPEREG_CALLTYPE typereg_reader_getDocumentation(void * hEntry, rtl_uString** pDoku)
1244{
1245 TypeRegistryEntry* pEntry = static_cast<TypeRegistryEntry*>(hEntry);
1246 if (pEntry != nullptr) {
1247 try {
1248 const char* pTmp = pEntry->m_pCP->readUTF8NameConstant(pEntry->readUINT16(OFFSET_DOKU));
1249 rtl_string2UString(
1250 pDoku, pTmp, pTmp == nullptr ? 0 : rtl_str_getLength(pTmp),
1251 RTL_TEXTENCODING_UTF8, OSTRING_TO_OUSTRING_CVTFLAGS);
1252 return;
1253 } catch (BlopObject::BoundsError &) {
1254 SAL_WARN("registry", "bad data");
1255 }
1256 }
1257 rtl_uString_new(pDoku);
1258}
1259
1260void TYPEREG_CALLTYPE typereg_reader_getFileName(void * hEntry, rtl_uString** pFileName)
1261{
1262 TypeRegistryEntry* pEntry = static_cast<TypeRegistryEntry*>(hEntry);
1263 if (pEntry != nullptr) {
1264 try {
1265 const char* pTmp = pEntry->m_pCP->readUTF8NameConstant(pEntry->readUINT16(OFFSET_FILENAME));
1266 rtl_string2UString(
1267 pFileName, pTmp, pTmp == nullptr ? 0 : rtl_str_getLength(pTmp),
1268 RTL_TEXTENCODING_UTF8, OSTRING_TO_OUSTRING_CVTFLAGS);
1269 return;
1270 } catch (BlopObject::BoundsError &) {
1271 SAL_WARN("registry", "bad data");
1272 }
1273 }
1274 rtl_uString_new(pFileName);
1275}
1276
1277
1279{
1280 TypeRegistryEntry* pEntry = static_cast<TypeRegistryEntry*>(hEntry);
1281
1282 if (pEntry == nullptr) return 0;
1283
1284 return pEntry->m_pFields->m_numOfEntries;
1285}
1286
1287void TYPEREG_CALLTYPE typereg_reader_getFieldName(void * hEntry, rtl_uString** pFieldName, sal_uInt16 index)
1288{
1289 TypeRegistryEntry* pEntry = static_cast<TypeRegistryEntry*>(hEntry);
1290
1291 if (pEntry == nullptr)
1292 {
1293 rtl_uString_new(pFieldName);
1294 return;
1295 }
1296 const char* pTmp = pEntry->m_pFields->getFieldName(index);
1297 rtl_string2UString(
1298 pFieldName, pTmp, pTmp == nullptr ? 0 : rtl_str_getLength(pTmp),
1299 RTL_TEXTENCODING_UTF8, OSTRING_TO_OUSTRING_CVTFLAGS);
1300}
1301
1302void TYPEREG_CALLTYPE typereg_reader_getFieldTypeName(void * hEntry, rtl_uString** pFieldType, sal_uInt16 index)
1303{
1304 TypeRegistryEntry* pEntry = static_cast<TypeRegistryEntry*>(hEntry);
1305
1306 if (pEntry == nullptr)
1307 {
1308 rtl_uString_new(pFieldType);
1309 return;
1310 }
1311
1312 const char* pTmp = pEntry->m_pFields->getFieldType(index);
1313 rtl_string2UString(
1314 pFieldType, pTmp, pTmp == nullptr ? 0 : rtl_str_getLength(pTmp),
1315 RTL_TEXTENCODING_UTF8, OSTRING_TO_OUSTRING_CVTFLAGS);
1316}
1317
1319{
1320 TypeRegistryEntry* pEntry = static_cast<TypeRegistryEntry*>(hEntry);
1321
1322 if (pEntry == nullptr) return RTFieldAccess::INVALID;
1323
1324 return pEntry->m_pFields->getFieldAccess(index);
1325}
1326
1328 void * hEntry, sal_uInt16 index, RTValueType * type,
1329 RTConstValueUnion * value)
1330{
1331 TypeRegistryEntry* pEntry = static_cast<TypeRegistryEntry*>(hEntry);
1332
1333 if (pEntry == nullptr) {
1334 *type = RT_TYPE_NONE;
1335 return true;
1336 }
1337
1338 try {
1339 *type = pEntry->m_pFields->getFieldConstValue(index, value);
1340 } catch (std::bad_alloc &) {
1341 return false;
1342 }
1343 return true;
1344}
1345
1346void TYPEREG_CALLTYPE typereg_reader_getFieldDocumentation(void * hEntry, rtl_uString** pDoku, sal_uInt16 index)
1347{
1348 TypeRegistryEntry* pEntry = static_cast<TypeRegistryEntry*>(hEntry);
1349
1350 if (pEntry == nullptr)
1351 {
1352 rtl_uString_new(pDoku);
1353 return;
1354 }
1355
1356 const char* pTmp = pEntry->m_pFields->getFieldDoku(index);
1357 rtl_string2UString(
1358 pDoku, pTmp, pTmp == nullptr ? 0 : rtl_str_getLength(pTmp),
1359 RTL_TEXTENCODING_UTF8, OSTRING_TO_OUSTRING_CVTFLAGS);
1360}
1361
1362void TYPEREG_CALLTYPE typereg_reader_getFieldFileName(void * hEntry, rtl_uString** pFieldFileName, sal_uInt16 index)
1363{
1364 TypeRegistryEntry* pEntry = static_cast<TypeRegistryEntry*>(hEntry);
1365
1366 if (pEntry == nullptr)
1367 {
1368 rtl_uString_new(pFieldFileName);
1369 return;
1370 }
1371
1372 const char* pTmp = pEntry->m_pFields->getFieldFileName(index);
1373 rtl_string2UString(
1374 pFieldFileName, pTmp, pTmp == nullptr ? 0 : rtl_str_getLength(pTmp),
1375 RTL_TEXTENCODING_UTF8, OSTRING_TO_OUSTRING_CVTFLAGS);
1376}
1377
1378
1380{
1381 TypeRegistryEntry* pEntry = static_cast<TypeRegistryEntry*>(hEntry);
1382
1383 if (pEntry == nullptr) return 0;
1384
1385 return pEntry->m_pMethods->m_numOfEntries;
1386}
1387
1388void TYPEREG_CALLTYPE typereg_reader_getMethodName(void * hEntry, rtl_uString** pMethodName, sal_uInt16 index)
1389{
1390 TypeRegistryEntry* pEntry = static_cast<TypeRegistryEntry*>(hEntry);
1391
1392 if (pEntry == nullptr)
1393 {
1394 rtl_uString_new(pMethodName);
1395 return;
1396 }
1397
1398 const char* pTmp = pEntry->m_pMethods->getMethodName(index);
1399 rtl_string2UString(
1400 pMethodName, pTmp, pTmp == nullptr ? 0 : rtl_str_getLength(pTmp),
1401 RTL_TEXTENCODING_UTF8, OSTRING_TO_OUSTRING_CVTFLAGS);
1402}
1403
1405 void * hEntry, sal_uInt16 index)
1406{
1407 TypeRegistryEntry* pEntry = static_cast<TypeRegistryEntry*>(hEntry);
1408
1409 if (pEntry == nullptr) return 0;
1410
1411 return pEntry->m_pMethods->getMethodParamCount(index);
1412}
1413
1414void TYPEREG_CALLTYPE typereg_reader_getMethodParameterTypeName(void * hEntry, rtl_uString** pMethodParamType, sal_uInt16 index, sal_uInt16 paramIndex)
1415{
1416 TypeRegistryEntry* pEntry = static_cast<TypeRegistryEntry*>(hEntry);
1417
1418 if (pEntry == nullptr)
1419 {
1420 rtl_uString_new(pMethodParamType);
1421 return;
1422 }
1423
1424 const char* pTmp = pEntry->m_pMethods->getMethodParamType(index, paramIndex);
1425 rtl_string2UString(
1426 pMethodParamType, pTmp, pTmp == nullptr ? 0 : rtl_str_getLength(pTmp),
1427 RTL_TEXTENCODING_UTF8, OSTRING_TO_OUSTRING_CVTFLAGS);
1428}
1429
1430void TYPEREG_CALLTYPE typereg_reader_getMethodParameterName(void * hEntry, rtl_uString** pMethodParamName, sal_uInt16 index, sal_uInt16 paramIndex)
1431{
1432 TypeRegistryEntry* pEntry = static_cast<TypeRegistryEntry*>(hEntry);
1433
1434 if (pEntry == nullptr)
1435 {
1436 rtl_uString_new(pMethodParamName);
1437 return;
1438 }
1439
1440 const char* pTmp = pEntry->m_pMethods->getMethodParamName(index, paramIndex);
1441 rtl_string2UString(
1442 pMethodParamName, pTmp, pTmp == nullptr ? 0 : rtl_str_getLength(pTmp),
1443 RTL_TEXTENCODING_UTF8, OSTRING_TO_OUSTRING_CVTFLAGS);
1444}
1445
1446RTParamMode TYPEREG_CALLTYPE typereg_reader_getMethodParameterFlags(void * hEntry, sal_uInt16 index, sal_uInt16 paramIndex)
1447{
1448 TypeRegistryEntry* pEntry = static_cast<TypeRegistryEntry*>(hEntry);
1449
1450 if (pEntry == nullptr) return RT_PARAM_INVALID;
1451
1452 return pEntry->m_pMethods->getMethodParamMode(index, paramIndex);
1453}
1454
1456 void * hEntry, sal_uInt16 index)
1457{
1458 TypeRegistryEntry* pEntry = static_cast<TypeRegistryEntry*>(hEntry);
1459
1460 if (pEntry == nullptr) return 0;
1461
1462 return pEntry->m_pMethods->getMethodExcCount(index);
1463}
1464
1465void TYPEREG_CALLTYPE typereg_reader_getMethodExceptionTypeName(void * hEntry, rtl_uString** pMethodExcpType, sal_uInt16 index, sal_uInt16 excIndex)
1466{
1467 TypeRegistryEntry* pEntry = static_cast<TypeRegistryEntry*>(hEntry);
1468
1469 if (pEntry == nullptr)
1470 {
1471 rtl_uString_new(pMethodExcpType);
1472 return;
1473 }
1474
1475 const char* pTmp = pEntry->m_pMethods->getMethodExcType(index, excIndex);
1476 rtl_string2UString(
1477 pMethodExcpType, pTmp, pTmp == nullptr ? 0 : rtl_str_getLength(pTmp),
1478 RTL_TEXTENCODING_UTF8, OSTRING_TO_OUSTRING_CVTFLAGS);
1479}
1480
1481void TYPEREG_CALLTYPE typereg_reader_getMethodReturnTypeName(void * hEntry, rtl_uString** pMethodReturnType, sal_uInt16 index)
1482{
1483 TypeRegistryEntry* pEntry = static_cast<TypeRegistryEntry*>(hEntry);
1484
1485 if (pEntry == nullptr)
1486 {
1487 rtl_uString_new(pMethodReturnType);
1488 return;
1489 }
1490
1491 const char* pTmp = pEntry->m_pMethods->getMethodReturnType(index);
1492 rtl_string2UString(
1493 pMethodReturnType, pTmp, pTmp == nullptr ? 0 : rtl_str_getLength(pTmp),
1494 RTL_TEXTENCODING_UTF8, OSTRING_TO_OUSTRING_CVTFLAGS);
1495}
1496
1498{
1499 TypeRegistryEntry* pEntry = static_cast<TypeRegistryEntry*>(hEntry);
1500
1501 if (pEntry == nullptr) return RTMethodMode::INVALID;
1502
1503 return pEntry->m_pMethods->getMethodMode(index);
1504}
1505
1506void TYPEREG_CALLTYPE typereg_reader_getMethodDocumentation(void * hEntry, rtl_uString** pMethodDoku, sal_uInt16 index)
1507{
1508 TypeRegistryEntry* pEntry = static_cast<TypeRegistryEntry*>(hEntry);
1509
1510 if (pEntry == nullptr)
1511 {
1512 rtl_uString_new(pMethodDoku);
1513 return;
1514 }
1515
1516 const char* pTmp = pEntry->m_pMethods->getMethodDoku(index);
1517 rtl_string2UString(
1518 pMethodDoku, pTmp, pTmp == nullptr ? 0 : rtl_str_getLength(pTmp),
1519 RTL_TEXTENCODING_UTF8, OSTRING_TO_OUSTRING_CVTFLAGS);
1520}
1521
1523{
1524 TypeRegistryEntry* pEntry = static_cast<TypeRegistryEntry*>(hEntry);
1525
1526 if (pEntry == nullptr) return 0;
1527
1528 return pEntry->m_pReferences->m_numOfEntries;
1529}
1530
1531void TYPEREG_CALLTYPE typereg_reader_getReferenceTypeName(void * hEntry, rtl_uString** pReferenceName, sal_uInt16 index)
1532{
1533 TypeRegistryEntry* pEntry = static_cast<TypeRegistryEntry*>(hEntry);
1534
1535 if (pEntry == nullptr)
1536 {
1537 rtl_uString_new(pReferenceName);
1538 return;
1539 }
1540
1541 const char* pTmp = pEntry->m_pReferences->getReferenceName(index);
1542 rtl_string2UString(
1543 pReferenceName, pTmp, pTmp == nullptr ? 0 : rtl_str_getLength(pTmp),
1544 RTL_TEXTENCODING_UTF8, OSTRING_TO_OUSTRING_CVTFLAGS);
1545}
1546
1548{
1549 TypeRegistryEntry* pEntry = static_cast<TypeRegistryEntry*>(hEntry);
1550
1551 if (pEntry == nullptr) return RTReferenceType::INVALID;
1552
1553 return pEntry->m_pReferences->getReferenceType(index);
1554}
1555
1556void TYPEREG_CALLTYPE typereg_reader_getReferenceDocumentation(void * hEntry, rtl_uString** pReferenceDoku, sal_uInt16 index)
1557{
1558 TypeRegistryEntry* pEntry = static_cast<TypeRegistryEntry*>(hEntry);
1559
1560 if (pEntry == nullptr)
1561 {
1562 rtl_uString_new(pReferenceDoku);
1563 return;
1564 }
1565
1566 const char* pTmp = pEntry->m_pReferences->getReferenceDoku(index);
1567 rtl_string2UString(
1568 pReferenceDoku, pTmp, pTmp == nullptr ? 0 : rtl_str_getLength(pTmp),
1569 RTL_TEXTENCODING_UTF8, OSTRING_TO_OUSTRING_CVTFLAGS);
1570}
1571
1573{
1574 TypeRegistryEntry* pEntry = static_cast<TypeRegistryEntry*>(hEntry);
1575
1576 if (pEntry == nullptr) return RTFieldAccess::INVALID;
1577
1578 return pEntry->m_pReferences->getReferenceAccess(index);
1579}
1580
1582{
1583 TypeRegistryEntry* pEntry = static_cast<TypeRegistryEntry*>(hEntry);
1584
1585 if (pEntry == nullptr) return 0;
1586
1587 return pEntry->m_nSuperTypes;
1588}
1589
1591 void * hEntry, rtl_uString ** pSuperTypeName, sal_uInt16 index)
1592{
1593 TypeRegistryEntry* pEntry = static_cast<TypeRegistryEntry*>(hEntry);
1594 if (pEntry != nullptr) {
1595 try {
1596 OSL_ASSERT(index < pEntry->m_nSuperTypes);
1597 const char* pTmp = pEntry->m_pCP->readUTF8NameConstant(pEntry->readUINT16(pEntry->m_offset_SUPERTYPES + (index * sizeof(sal_uInt16))));
1598 rtl_string2UString(
1599 pSuperTypeName, pTmp, pTmp == nullptr ? 0 : rtl_str_getLength(pTmp),
1600 RTL_TEXTENCODING_UTF8, OSTRING_TO_OUSTRING_CVTFLAGS);
1601 return;
1602 } catch (BlopObject::BoundsError &) {
1603 SAL_WARN("registry", "bad data");
1604 }
1605 }
1606 rtl_uString_new(pSuperTypeName);
1607}
1608
1609/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Any value
sal_uInt8 m_pBuffer[RTL_DIGEST_LENGTH_SHA1]
ULONG m_refCount
float v
float x
OUString aName
sal_Int64 n
#define SAL_WARN(area, stream)
size
OUString getString(const Any &_rAny)
sal_Int32 getFieldType(guint nCol)
OUString getFieldName(guint nCol)
int i
index
css::uno::Reference< css::linguistic2::XProofreadingIterator > get(css::uno::Reference< css::uno::XComponentContext > const &context)
#define METHOD_OFFSET_PARAM_COUNT
Definition: reflcnst.hxx:70
#define REFERENCE_OFFSET_TYPE
Definition: reflcnst.hxx:72
#define REFERENCE_OFFSET_NAME
Definition: reflcnst.hxx:73
#define OFFSET_DOKU
Definition: reflcnst.hxx:41
sal_uInt32 readUINT16(const sal_uInt8 *buffer, sal_uInt16 &v)
Definition: reflcnst.hxx:102
#define REFERENCE_OFFSET_DOKU
Definition: reflcnst.hxx:74
#define CP_OFFSET_ENTRY_DATA
Definition: reflcnst.hxx:52
#define REFERENCE_OFFSET_ACCESS
Definition: reflcnst.hxx:75
#define FIELD_OFFSET_TYPE
Definition: reflcnst.hxx:56
#define PARAM_OFFSET_MODE
Definition: reflcnst.hxx:62
#define METHOD_OFFSET_DOKU
Definition: reflcnst.hxx:69
#define OFFSET_THIS_TYPE
Definition: reflcnst.hxx:39
#define METHOD_OFFSET_RETURN
Definition: reflcnst.hxx:68
sal_uInt32 readString(const sal_uInt8 *buffer, sal_Unicode *v, sal_uInt32 maxSize)
Definition: reflwrit.cxx:54
sal_uInt32 readINT32(const sal_uInt8 *buffer, sal_Int32 &v)
Definition: reflcnst.hxx:123
#define FIELD_OFFSET_FILENAME
Definition: reflcnst.hxx:59
sal_uInt32 readUINT32(const sal_uInt8 *buffer, sal_uInt32 &v)
Definition: reflcnst.hxx:145
#define PARAM_OFFSET_NAME
Definition: reflcnst.hxx:63
#define PARAM_OFFSET_TYPE
Definition: reflcnst.hxx:61
#define OFFSET_MAGIC
Definition: reflcnst.hxx:32
#define FIELD_OFFSET_VALUE
Definition: reflcnst.hxx:57
sal_uInt32 UINT16StringLen(const sal_uInt8 *wstring)
Definition: reflwrit.cxx:29
#define OFFSET_FILENAME
Definition: reflcnst.hxx:42
#define FIELD_OFFSET_DOKU
Definition: reflcnst.hxx:58
CPInfoTag
Definition: reflcnst.hxx:78
@ CP_TAG_CONST_BYTE
Definition: reflcnst.hxx:81
@ CP_TAG_CONST_FLOAT
Definition: reflcnst.hxx:88
@ CP_TAG_CONST_DOUBLE
Definition: reflcnst.hxx:89
@ CP_TAG_CONST_UINT32
Definition: reflcnst.hxx:85
@ CP_TAG_CONST_UINT16
Definition: reflcnst.hxx:83
@ CP_TAG_CONST_INT64
Definition: reflcnst.hxx:86
@ CP_TAG_CONST_INT32
Definition: reflcnst.hxx:84
@ CP_TAG_CONST_INT16
Definition: reflcnst.hxx:82
@ CP_TAG_INVALID
Definition: reflcnst.hxx:79
@ CP_TAG_CONST_BOOL
Definition: reflcnst.hxx:80
@ CP_TAG_CONST_UINT64
Definition: reflcnst.hxx:87
@ CP_TAG_UTF8_NAME
Definition: reflcnst.hxx:91
@ CP_TAG_CONST_STRING
Definition: reflcnst.hxx:90
#define CP_OFFSET_ENTRY_TAG
Definition: reflcnst.hxx:51
#define OFFSET_TYPE_CLASS
Definition: reflcnst.hxx:38
#define OFFSET_N_ENTRIES
Definition: reflcnst.hxx:36
#define METHOD_OFFSET_MODE
Definition: reflcnst.hxx:66
#define FIELD_OFFSET_NAME
Definition: reflcnst.hxx:55
#define METHOD_OFFSET_NAME
Definition: reflcnst.hxx:67
#define FIELD_OFFSET_ACCESS
Definition: reflcnst.hxx:54
#define OFFSET_SIZE
Definition: reflcnst.hxx:33
const sal_uInt32 magic
Definition: reflread.cxx:43
void TYPEREG_CALLTYPE typereg_reader_getFieldDocumentation(void *hEntry, rtl_uString **pDoku, sal_uInt16 index)
Returns the documentation of a field of a type reader.
Definition: reflread.cxx:1346
sal_uInt16 TYPEREG_CALLTYPE typereg_reader_getMethodExceptionCount(void *hEntry, sal_uInt16 index)
Returns the number of exceptions of a method of a type reader.
Definition: reflread.cxx:1455
sal_uInt16 TYPEREG_CALLTYPE typereg_reader_getReferenceCount(void *hEntry)
Returns the number of references of a type reader.
Definition: reflread.cxx:1522
void TYPEREG_CALLTYPE typereg_reader_getFieldFileName(void *hEntry, rtl_uString **pFieldFileName, sal_uInt16 index)
Returns the file name of a field of a type reader.
Definition: reflread.cxx:1362
void TYPEREG_CALLTYPE typereg_reader_getFileName(void *hEntry, rtl_uString **pFileName)
Returns the file name of a type reader.
Definition: reflread.cxx:1260
bool TYPEREG_CALLTYPE typereg_reader_getFieldValue(void *hEntry, sal_uInt16 index, RTValueType *type, RTConstValueUnion *value)
Returns the value of a field of a type reader.
Definition: reflread.cxx:1327
const sal_uInt16 majorVersion
Definition: reflread.cxx:45
void TYPEREG_CALLTYPE typereg_reader_getSuperTypeName(void *hEntry, rtl_uString **pSuperTypeName, sal_uInt16 index)
Returns the type name of a super type of a type reader.
Definition: reflread.cxx:1590
sal_uInt16 TYPEREG_CALLTYPE typereg_reader_getMethodCount(void *hEntry)
Returns the number of methods of a type reader.
Definition: reflread.cxx:1379
void TYPEREG_CALLTYPE typereg_reader_acquire(void *hEntry)
Increments the reference count of a type reader.
Definition: reflread.cxx:1169
void TYPEREG_CALLTYPE typereg_reader_getDocumentation(void *hEntry, rtl_uString **pDoku)
Returns the documentation of a type reader.
Definition: reflread.cxx:1243
void TYPEREG_CALLTYPE typereg_reader_getMethodParameterName(void *hEntry, rtl_uString **pMethodParamName, sal_uInt16 index, sal_uInt16 paramIndex)
Returns the name of a parameter of a method of a type reader.
Definition: reflread.cxx:1430
bool TYPEREG_CALLTYPE typereg_reader_create(void const *buffer, sal_uInt32 length, void **result)
Creates a type reader working on a binary blob that represents a UNOIDL type.
Definition: reflread.cxx:1135
void TYPEREG_CALLTYPE typereg_reader_release(void *hEntry)
Decrements the reference count of a type reader.
Definition: reflread.cxx:1177
typereg_Version TYPEREG_CALLTYPE typereg_reader_getVersion(void const *handle)
Returns the binary blob version of a type reader.
Definition: reflread.cxx:1188
const sal_Unicode NULL_WSTRING[1]
Definition: reflread.cxx:41
RTTypeClass TYPEREG_CALLTYPE typereg_reader_getTypeClass(void *hEntry)
Returns the type class of a type reader.
Definition: reflread.cxx:1199
const sal_uInt16 minorVersion
Definition: reflread.cxx:44
void TYPEREG_CALLTYPE typereg_reader_getFieldName(void *hEntry, rtl_uString **pFieldName, sal_uInt16 index)
Returns the name of a field of a type reader.
Definition: reflread.cxx:1287
bool TYPEREG_CALLTYPE typereg_reader_isPublished(void *hEntry)
Returns whether a type reader is published.
Definition: reflread.cxx:1212
void TYPEREG_CALLTYPE typereg_reader_getTypeName(void *hEntry, rtl_uString **pTypeName)
Returns the type name of a type reader.
Definition: reflread.cxx:1225
RTMethodMode TYPEREG_CALLTYPE typereg_reader_getMethodFlags(void *hEntry, sal_uInt16 index)
Returns the flags of a method of a type reader.
Definition: reflread.cxx:1497
void TYPEREG_CALLTYPE typereg_reader_getFieldTypeName(void *hEntry, rtl_uString **pFieldType, sal_uInt16 index)
Returns the type name of a field of a type reader.
Definition: reflread.cxx:1302
sal_uInt16 TYPEREG_CALLTYPE typereg_reader_getSuperTypeCount(void *hEntry)
Returns the number of super types of a type reader.
Definition: reflread.cxx:1581
RTFieldAccess TYPEREG_CALLTYPE typereg_reader_getFieldFlags(void *hEntry, sal_uInt16 index)
Returns the flags of a field of a type reader.
Definition: reflread.cxx:1318
RTParamMode TYPEREG_CALLTYPE typereg_reader_getMethodParameterFlags(void *hEntry, sal_uInt16 index, sal_uInt16 paramIndex)
Returns the flags of a parameter of a method of a type reader.
Definition: reflread.cxx:1446
void TYPEREG_CALLTYPE typereg_reader_getMethodName(void *hEntry, rtl_uString **pMethodName, sal_uInt16 index)
Returns the name of a method of a type reader.
Definition: reflread.cxx:1388
void TYPEREG_CALLTYPE typereg_reader_getReferenceDocumentation(void *hEntry, rtl_uString **pReferenceDoku, sal_uInt16 index)
Returns the documentation of a reference of a type reader.
Definition: reflread.cxx:1556
void TYPEREG_CALLTYPE typereg_reader_getMethodReturnTypeName(void *hEntry, rtl_uString **pMethodReturnType, sal_uInt16 index)
Returns the return type name of a method of a type reader.
Definition: reflread.cxx:1481
RTReferenceType TYPEREG_CALLTYPE typereg_reader_getReferenceSort(void *hEntry, sal_uInt16 index)
Returns the sort of a reference of a type reader.
Definition: reflread.cxx:1547
void TYPEREG_CALLTYPE typereg_reader_getMethodExceptionTypeName(void *hEntry, rtl_uString **pMethodExcpType, sal_uInt16 index, sal_uInt16 excIndex)
Returns the type name of an exception of a method of a type reader.
Definition: reflread.cxx:1465
void TYPEREG_CALLTYPE typereg_reader_getMethodParameterTypeName(void *hEntry, rtl_uString **pMethodParamType, sal_uInt16 index, sal_uInt16 paramIndex)
Returns the type name of a parameter of a method of a type reader.
Definition: reflread.cxx:1414
void TYPEREG_CALLTYPE typereg_reader_getMethodDocumentation(void *hEntry, rtl_uString **pMethodDoku, sal_uInt16 index)
Returns the documentation of a method of a type reader.
Definition: reflread.cxx:1506
const char NULL_STRING[1]
Definition: reflread.cxx:40
RTFieldAccess TYPEREG_CALLTYPE typereg_reader_getReferenceFlags(void *hEntry, sal_uInt16 index)
Returns the flags of a reference of a type reader.
Definition: reflread.cxx:1572
sal_uInt16 TYPEREG_CALLTYPE typereg_reader_getMethodParameterCount(void *hEntry, sal_uInt16 index)
Returns the number of parameters of a method of a type reader.
Definition: reflread.cxx:1404
sal_uInt16 TYPEREG_CALLTYPE typereg_reader_getFieldCount(void *hEntry)
Returns the number of fields of a type reader.
Definition: reflread.cxx:1278
void TYPEREG_CALLTYPE typereg_reader_getReferenceTypeName(void *hEntry, rtl_uString **pReferenceName, sal_uInt16 index)
Returns the type name of a reference of a type reader.
Definition: reflread.cxx:1531
#define TYPEREG_CALLTYPE
specifies the calling convention for type reader/writer api
Definition: refltype.hxx:47
unsigned char sal_uInt8
sal_uInt16 sal_Unicode
signed char sal_Int8
#define SAL_MAX_UINT32
RTReferenceType
specifies the type of a reference used in a service description.
Definition: types.hxx:303
@ INVALID
the reference type is unknown
RTParamMode
specifies the mode of a parameter.
Definition: types.hxx:274
@ RT_PARAM_INVALID
indicates an invalid parameter mode
Definition: types.hxx:276
RTValueType
specifies the type of a field value.
Definition: types.hxx:198
@ RT_TYPE_BYTE
Definition: types.hxx:201
@ RT_TYPE_FLOAT
Definition: types.hxx:208
@ RT_TYPE_INT64
Definition: types.hxx:206
@ RT_TYPE_INT32
Definition: types.hxx:204
@ RT_TYPE_DOUBLE
Definition: types.hxx:209
@ RT_TYPE_NONE
Definition: types.hxx:199
@ RT_TYPE_UINT16
Definition: types.hxx:203
@ RT_TYPE_BOOL
Definition: types.hxx:200
@ RT_TYPE_STRING
Definition: types.hxx:210
@ RT_TYPE_UINT64
Definition: types.hxx:207
@ RT_TYPE_UINT32
Definition: types.hxx:205
@ RT_TYPE_INT16
Definition: types.hxx:202
RTFieldAccess
specifies the type for the field access.
Definition: types.hxx:133
@ INVALID
specifies an unknown flag
RTMethodMode
specifies the mode of a method.
Definition: types.hxx:235
@ INVALID
indicates an invalid mode
RTTypeClass
specifies the typeclass of a binary type blob.
Definition: types.hxx:31
@ RT_TYPE_INVALID
specifies that the structure of the given blob is unknown and can't be read.
Definition: types.hxx:35
Any result
ResultType type
specifies a variable container for field values.
Definition: types.hxx:215
typereg_Version
The version of a binary blob that represents a UNOIDL type.
Definition: version.h:40
@ TYPEREG_VERSION_0
Denotes the original version of UNOIDL type blobs.
Definition: version.h:44
@ TYPEREG_VERSION_1
Denotes the updated version of UNOIDL type blobs.
Definition: version.h:54