1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
21 #include "regimpl.hxx"
26 #include <string_view>
35 #include "reflread.hxx"
37 #include "reflwrit.hxx"
39 #include <registry/reader.hxx>
40 #include <registry/refltype.hxx>
41 #include <registry/types.hxx>
43 #include "reflcnst.hxx"
44 #include "keyimpl.hxx"
46 #include <osl/thread.h>
47 #include <rtl/ustring.hxx>
48 #include <rtl/ustrbuf.hxx>
49 #include <osl/file.hxx>
52 using namespace store
;
57 void printString(std::u16string_view s
) {
59 for (std::size_t i
= 0; i
< s
.size(); ++i
) {
61 if (c
== '"' || c
== '\\') {
62 printf("\\%c", static_cast< char >(c
));
63 } else if (s
[i
] >= ' ' && s
[i
] <= '~') {
64 printf("%c", static_cast< char >(c
));
66 printf("\\u%04X", static_cast< unsigned int >(c
));
72 void printFieldOrReferenceFlag(
73 RTFieldAccess
* flags
, RTFieldAccess flag
, char const * name
, bool * first
)
75 if ((*flags
& flag
) != RTFieldAccess::NONE
) {
85 void printFieldOrReferenceFlags(RTFieldAccess flags
) {
86 if (flags
== RTFieldAccess::NONE
) {
90 printFieldOrReferenceFlag(
91 &flags
, RTFieldAccess::READONLY
, "readonly", &first
);
92 printFieldOrReferenceFlag(
93 &flags
, RTFieldAccess::OPTIONAL
, "optional", &first
);
94 printFieldOrReferenceFlag(
95 &flags
, RTFieldAccess::MAYBEVOID
, "maybevoid", &first
);
96 printFieldOrReferenceFlag(&flags
, RTFieldAccess::BOUND
, "bound", &first
);
97 printFieldOrReferenceFlag(
98 &flags
, RTFieldAccess::CONSTRAINED
, "constrained", &first
);
99 printFieldOrReferenceFlag(
100 &flags
, RTFieldAccess::TRANSIENT
, "transient", &first
);
101 printFieldOrReferenceFlag(
102 &flags
, RTFieldAccess::MAYBEAMBIGUOUS
, "maybeambiguous", &first
);
103 printFieldOrReferenceFlag(
104 &flags
, RTFieldAccess::MAYBEDEFAULT
, "maybedefault", &first
);
105 printFieldOrReferenceFlag(
106 &flags
, RTFieldAccess::REMOVABLE
, "removable", &first
);
107 printFieldOrReferenceFlag(
108 &flags
, RTFieldAccess::ATTRIBUTE
, "attribute", &first
);
109 printFieldOrReferenceFlag(
110 &flags
, RTFieldAccess::PROPERTY
, "property", &first
);
111 printFieldOrReferenceFlag(&flags
, RTFieldAccess::CONST
, "const", &first
);
112 printFieldOrReferenceFlag(
113 &flags
, RTFieldAccess::READWRITE
, "readwrite", &first
);
114 printFieldOrReferenceFlag(
115 &flags
, RTFieldAccess::PARAMETERIZED_TYPE
, "parameterized type", &first
);
116 printFieldOrReferenceFlag(
117 &flags
, RTFieldAccess::PUBLISHED
, "published", &first
);
118 if (flags
!= RTFieldAccess::NONE
) {
122 printf("<invalid (0x%04X)>", static_cast< unsigned int >(flags
));
127 void dumpType(typereg::Reader
const & reader
, OString
const & indent
) {
128 if (reader
.isValid()) {
129 printf("version: %ld\n", static_cast< long >(reader
.getVersion()));
130 printf("%sdocumentation: ", indent
.getStr());
131 printString(reader
.getDocumentation());
133 printf("%sfile name: ", indent
.getStr());
134 printString(reader
.getFileName());
136 printf("%stype class: ", indent
.getStr());
137 if (reader
.isPublished()) {
138 printf("published ");
140 switch (reader
.getTypeClass()) {
141 case RT_TYPE_INTERFACE
:
157 case RT_TYPE_EXCEPTION
:
161 case RT_TYPE_TYPEDEF
:
165 case RT_TYPE_SERVICE
:
169 case RT_TYPE_SINGLETON
:
173 case RT_TYPE_CONSTANTS
:
179 "<invalid (%ld)>", static_cast< long >(reader
.getTypeClass()));
183 printf("%stype name: ", indent
.getStr());
184 printString(reader
.getTypeName());
187 "%ssuper type count: %u\n", indent
.getStr(),
188 static_cast< unsigned int >(reader
.getSuperTypeCount()));
189 for (sal_uInt16 i
= 0; i
< reader
.getSuperTypeCount(); ++i
) {
191 "%ssuper type name %u: ", indent
.getStr(),
192 static_cast< unsigned int >(i
));
193 printString(reader
.getSuperTypeName(i
));
197 "%sfield count: %u\n", indent
.getStr(),
198 static_cast< unsigned int >(reader
.getFieldCount()));
199 for (sal_uInt16 i
= 0; i
< reader
.getFieldCount(); ++i
) {
201 "%sfield %u:\n", indent
.getStr(),
202 static_cast< unsigned int >(i
));
203 printf("%s documentation: ", indent
.getStr());
204 printString(reader
.getFieldDocumentation(i
));
206 printf("%s file name: ", indent
.getStr());
207 printString(reader
.getFieldFileName(i
));
209 printf("%s flags: ", indent
.getStr());
210 printFieldOrReferenceFlags(reader
.getFieldFlags(i
));
212 printf("%s name: ", indent
.getStr());
213 printString(reader
.getFieldName(i
));
215 printf("%s type name: ", indent
.getStr());
216 printString(reader
.getFieldTypeName(i
));
218 printf("%s value: ", indent
.getStr());
219 RTConstValue
value(reader
.getFieldValue(i
));
220 switch (value
.m_type
) {
226 printf("boolean %s", value
.m_value
.aBool
? "true" : "false");
230 printf("byte %d", static_cast< int >(value
.m_value
.aByte
));
234 printf("short %d", static_cast< int >(value
.m_value
.aShort
));
240 static_cast< unsigned int >(value
.m_value
.aUShort
));
244 printf("long %ld", static_cast< long >(value
.m_value
.aLong
));
250 static_cast< unsigned long >(value
.m_value
.aULong
));
254 // TODO: no portable way to print hyper values
259 // TODO: no portable way to print unsigned hyper values
260 printf("unsigned hyper");
264 // TODO: no portable way to print float values
269 // TODO: no portable way to print double values
275 printString(value
.m_value
.aString
);
279 printf("<invalid (%ld)>", static_cast< long >(value
.m_type
));
285 "%smethod count: %u\n", indent
.getStr(),
286 static_cast< unsigned int >(reader
.getMethodCount()));
287 for (sal_uInt16 i
= 0; i
< reader
.getMethodCount(); ++i
) {
289 "%smethod %u:\n", indent
.getStr(),
290 static_cast< unsigned int >(i
));
291 printf("%s documentation: ", indent
.getStr());
292 printString(reader
.getMethodDocumentation(i
));
294 printf("%s flags: ", indent
.getStr());
295 switch (reader
.getMethodFlags(i
)) {
296 case RTMethodMode::ONEWAY
:
300 case RTMethodMode::TWOWAY
:
301 printf("synchronous");
304 case RTMethodMode::ATTRIBUTE_GET
:
305 printf("attribute get");
308 case RTMethodMode::ATTRIBUTE_SET
:
309 printf("attribute set");
315 static_cast< long >(reader
.getMethodFlags(i
)));
319 printf("%s name: ", indent
.getStr());
320 printString(reader
.getMethodName(i
));
322 printf("%s return type name: ", indent
.getStr());
323 printString(reader
.getMethodReturnTypeName(i
));
326 "%s parameter count: %u\n", indent
.getStr(),
327 static_cast< unsigned int >(reader
.getMethodParameterCount(i
)));
328 // coverity[tainted_data] - cid#1215304 unhelpfully warns about untrusted loop bound
329 for (sal_uInt16 j
= 0; j
< reader
.getMethodParameterCount(i
); ++j
)
332 "%s parameter %u:\n", indent
.getStr(),
333 static_cast< unsigned int >(j
));
334 printf("%s flags: ", indent
.getStr());
335 RTParamMode flags
= reader
.getMethodParameterFlags(i
, j
);
336 bool rest
= (flags
& RT_PARAM_REST
) != 0;
337 switch (flags
& ~RT_PARAM_REST
) {
351 printf("<invalid (%ld)>", static_cast< long >(flags
));
359 printf("%s name: ", indent
.getStr());
360 printString(reader
.getMethodParameterName(i
, j
));
362 printf("%s type name: ", indent
.getStr());
363 printString(reader
.getMethodParameterTypeName(i
, j
));
367 "%s exception count: %u\n", indent
.getStr(),
368 static_cast< unsigned int >(reader
.getMethodExceptionCount(i
)));
369 // coverity[tainted_data] - cid#1215304 unhelpfully warns about untrusted loop bound
370 for (sal_uInt16 j
= 0; j
< reader
.getMethodExceptionCount(i
); ++j
)
373 "%s exception type name %u: ", indent
.getStr(),
374 static_cast< unsigned int >(j
));
375 printString(reader
.getMethodExceptionTypeName(i
, j
));
380 "%sreference count: %u\n", indent
.getStr(),
381 static_cast< unsigned int >(reader
.getReferenceCount()));
382 for (sal_uInt16 i
= 0; i
< reader
.getReferenceCount(); ++i
) {
384 "%sreference %u:\n", indent
.getStr(),
385 static_cast< unsigned int >(i
));
386 printf("%s documentation: ", indent
.getStr());
387 printString(reader
.getReferenceDocumentation(i
));
389 printf("%s flags: ", indent
.getStr());
390 printFieldOrReferenceFlags(reader
.getReferenceFlags(i
));
392 printf("%s sort: ", indent
.getStr());
393 switch (reader
.getReferenceSort(i
)) {
394 case RTReferenceType::SUPPORTS
:
398 case RTReferenceType::EXPORTS
:
402 case RTReferenceType::TYPE_PARAMETER
:
403 printf("type parameter");
409 static_cast< long >(reader
.getReferenceSort(i
)));
413 printf("%s type name: ", indent
.getStr());
414 printString(reader
.getReferenceTypeName(i
));
418 printf("<invalid>\n");
424 ORegistry::ORegistry()
431 ORegistry::~ORegistry()
433 ORegKey
* pRootKey
= m_openKeyTable
[ROOT
];
434 if (pRootKey
!= nullptr)
435 (void) releaseKey(pRootKey
);
437 if (m_file
.isValid())
441 RegError
ORegistry::initRegistry(const OUString
& regName
, RegAccessMode accessMode
, bool bCreate
)
443 RegError eRet
= RegError::INVALID_REGISTRY
;
445 storeAccessMode sAccessMode
= storeAccessMode::ReadWrite
;
450 sAccessMode
= storeAccessMode::Create
;
452 else if (accessMode
& RegAccessMode::READONLY
)
454 sAccessMode
= storeAccessMode::ReadOnly
;
458 if (regName
.isEmpty() &&
459 storeAccessMode::Create
== sAccessMode
)
461 errCode
= rRegFile
.createInMemory();
465 errCode
= rRegFile
.create(regName
, sAccessMode
);
472 case store_E_NotExists
:
473 eRet
= RegError::REGISTRY_NOT_EXISTS
;
475 case store_E_LockingViolation
:
476 eRet
= RegError::CANNOT_OPEN_FOR_READWRITE
;
479 eRet
= RegError::INVALID_REGISTRY
;
485 OStoreDirectory rStoreDir
;
486 storeError _err
= rStoreDir
.create(rRegFile
, OUString(), OUString(), sAccessMode
);
488 if (_err
== store_E_None
)
494 m_openKeyTable
[ROOT
] = new ORegKey(ROOT
, this);
495 eRet
= RegError::NO_ERROR
;
498 eRet
= RegError::INVALID_REGISTRY
;
504 RegError
ORegistry::closeRegistry()
508 if (m_file
.isValid())
510 (void) releaseKey(m_openKeyTable
[ROOT
]);
513 return RegError::NO_ERROR
;
516 return RegError::REGISTRY_NOT_EXISTS
;
520 RegError
ORegistry::destroyRegistry(const OUString
& regName
)
524 if (!regName
.isEmpty())
526 std::unique_ptr
<ORegistry
> pReg(new ORegistry());
528 if (pReg
->initRegistry(regName
, RegAccessMode::READWRITE
) == RegError::NO_ERROR
)
533 if (FileBase::getSystemPathFromFileURL(regName
, systemName
) != FileBase::E_None
)
534 systemName
= regName
;
536 OString
name(OUStringToOString(systemName
, osl_getThreadTextEncoding()));
537 if (unlink(name
.getStr()) != 0)
539 return RegError::DESTROY_REGISTRY_FAILED
;
543 return RegError::DESTROY_REGISTRY_FAILED
;
547 if (m_refCount
!= 1 || isReadOnly())
549 return RegError::DESTROY_REGISTRY_FAILED
;
552 if (m_file
.isValid())
554 releaseKey(m_openKeyTable
[ROOT
]);
558 if (!m_name
.isEmpty())
561 if (FileBase::getSystemPathFromFileURL(m_name
, systemName
) != FileBase::E_None
)
564 OString
name(OUStringToOString(systemName
, osl_getThreadTextEncoding()));
565 if (unlink(name
.getStr()) != 0)
567 return RegError::DESTROY_REGISTRY_FAILED
;
572 return RegError::REGISTRY_NOT_EXISTS
;
576 return RegError::NO_ERROR
;
579 RegError
ORegistry::acquireKey (RegKeyHandle hKey
)
581 ORegKey
* pKey
= static_cast< ORegKey
* >(hKey
);
583 return RegError::INVALID_KEY
;
588 return RegError::NO_ERROR
;
591 RegError
ORegistry::releaseKey (RegKeyHandle hKey
)
593 ORegKey
* pKey
= static_cast< ORegKey
* >(hKey
);
595 return RegError::INVALID_KEY
;
598 if (pKey
->release() == 0)
600 m_openKeyTable
.erase(pKey
->getName());
603 return RegError::NO_ERROR
;
606 RegError
ORegistry::createKey(RegKeyHandle hKey
, const OUString
& keyName
,
607 RegKeyHandle
* phNewKey
)
613 if (keyName
.isEmpty())
614 return RegError::INVALID_KEYNAME
;
619 pKey
= static_cast<ORegKey
*>(hKey
);
621 pKey
= m_openKeyTable
[ROOT
];
623 OUString sFullKeyName
= pKey
->getFullPath(keyName
);
625 if (m_openKeyTable
.count(sFullKeyName
) > 0)
627 *phNewKey
= m_openKeyTable
[sFullKeyName
];
628 static_cast<ORegKey
*>(*phNewKey
)->acquire();
629 static_cast<ORegKey
*>(*phNewKey
)->setDeleted(false);
630 return RegError::NO_ERROR
;
633 OStoreDirectory rStoreDir
;
634 OUStringBuffer
sFullPath(sFullKeyName
.getLength()+16);
637 sFullPath
.append('/');
639 sal_Int32 nIndex
= 0;
642 token
= sFullKeyName
.getToken(0, '/', nIndex
);
643 if (!token
.isEmpty())
645 if (rStoreDir
.create(pKey
->getStoreFile(), sFullPath
.toString(), token
, storeAccessMode::Create
))
647 return RegError::CREATE_KEY_FAILED
;
650 sFullPath
.append(token
);
651 sFullPath
.append('/');
653 } while(nIndex
!= -1);
656 pKey
= new ORegKey(sFullKeyName
, this);
658 m_openKeyTable
[sFullKeyName
] = pKey
;
660 return RegError::NO_ERROR
;
663 RegError
ORegistry::openKey(RegKeyHandle hKey
, const OUString
& keyName
,
664 RegKeyHandle
* phOpenKey
)
668 *phOpenKey
= nullptr;
670 if (keyName
.isEmpty())
672 return RegError::INVALID_KEYNAME
;
678 pKey
= static_cast<ORegKey
*>(hKey
);
680 pKey
= m_openKeyTable
[ROOT
];
682 OUString
path(pKey
->getFullPath(keyName
));
683 KeyMap::iterator
i(m_openKeyTable
.find(path
));
684 if (i
== m_openKeyTable
.end()) {
685 sal_Int32 n
= path
.lastIndexOf('/') + 1;
686 switch (OStoreDirectory().create(
687 pKey
->getStoreFile(), path
.copy(0, n
), path
.copy(n
),
688 isReadOnly() ? storeAccessMode::ReadOnly
: storeAccessMode::ReadWrite
))
690 case store_E_NotExists
:
691 return RegError::KEY_NOT_EXISTS
;
692 case store_E_WrongFormat
:
693 return RegError::INVALID_KEY
;
698 std::unique_ptr
< ORegKey
> p(new ORegKey(path
, this));
699 i
= m_openKeyTable
.insert(std::make_pair(path
, p
.get())).first
;
702 i
->second
->acquire();
704 *phOpenKey
= i
->second
;
705 return RegError::NO_ERROR
;
708 RegError
ORegistry::closeKey(RegKeyHandle hKey
)
710 ORegKey
* pKey
= static_cast< ORegKey
* >(hKey
);
714 OUString
const aKeyName (pKey
->getName());
715 if (m_openKeyTable
.count(aKeyName
) <= 0)
716 return RegError::KEY_NOT_OPEN
;
718 if (pKey
->isModified())
720 ORegKey
* pRootKey
= getRootKey();
721 if (pKey
!= pRootKey
)
723 // propagate "modified" state to RootKey.
724 pRootKey
->setModified();
728 // closing modified RootKey, flush registry file.
729 (void) m_file
.flush();
731 pKey
->setModified(false);
732 (void) releaseKey(pRootKey
);
735 return releaseKey(pKey
);
738 RegError
ORegistry::deleteKey(RegKeyHandle hKey
, const OUString
& keyName
)
740 ORegKey
* pKey
= static_cast< ORegKey
* >(hKey
);
741 if (keyName
.isEmpty())
742 return RegError::INVALID_KEYNAME
;
747 pKey
= m_openKeyTable
[ROOT
];
749 OUString
sFullKeyName(pKey
->getFullPath(keyName
));
750 return eraseKey(m_openKeyTable
[ROOT
], sFullKeyName
);
753 RegError
ORegistry::eraseKey(ORegKey
* pKey
, const OUString
& keyName
)
755 RegError _ret
= RegError::NO_ERROR
;
757 if (keyName
.isEmpty())
759 return RegError::INVALID_KEYNAME
;
762 OUString
sFullKeyName(pKey
->getName());
763 OUString
sFullPath(sFullKeyName
);
764 OUString sRelativKey
;
765 sal_Int32 lastIndex
= keyName
.lastIndexOf('/');
769 sRelativKey
+= keyName
.subView(lastIndex
+ 1);
771 if (sFullKeyName
.getLength() > 1)
772 sFullKeyName
+= keyName
;
774 sFullKeyName
+= keyName
.subView(1);
776 sFullPath
= sFullKeyName
.copy(0, keyName
.lastIndexOf('/') + 1);
779 if (sFullKeyName
.getLength() > 1)
780 sFullKeyName
+= ROOT
;
782 sRelativKey
+= keyName
;
783 sFullKeyName
+= keyName
;
785 if (sFullPath
.getLength() > 1)
789 ORegKey
* pOldKey
= nullptr;
790 _ret
= pKey
->openKey(keyName
, reinterpret_cast<RegKeyHandle
*>(&pOldKey
));
791 if (_ret
!= RegError::NO_ERROR
)
794 _ret
= deleteSubkeysAndValues(pOldKey
);
795 if (_ret
!= RegError::NO_ERROR
)
797 pKey
->closeKey(pOldKey
);
801 OUString tmpName
= sRelativKey
+ ROOT
;
803 OStoreFile
sFile(pKey
->getStoreFile());
804 if (sFile
.isValid() && sFile
.remove(sFullPath
, tmpName
))
806 return RegError::DELETE_KEY_FAILED
;
808 pOldKey
->setModified();
810 // set flag deleted !!!
811 pOldKey
->setDeleted(true);
813 return pKey
->closeKey(pOldKey
);
816 RegError
ORegistry::deleteSubkeysAndValues(ORegKey
* pKey
)
818 OStoreDirectory::iterator iter
;
819 RegError _ret
= RegError::NO_ERROR
;
820 OStoreDirectory
rStoreDir(pKey
->getStoreDir());
821 storeError _err
= rStoreDir
.first(iter
);
823 while (_err
== store_E_None
)
825 OUString
const keyName(iter
.m_pszName
, iter
.m_nLength
);
827 if (iter
.m_nAttrib
& STORE_ATTRIB_ISDIR
)
829 _ret
= eraseKey(pKey
, keyName
);
830 if (_ret
!= RegError::NO_ERROR
)
835 OUString
sFullPath(pKey
->getName());
837 if (sFullPath
.getLength() > 1)
840 if (const_cast<OStoreFile
&>(pKey
->getStoreFile()).remove(sFullPath
, keyName
))
842 return RegError::DELETE_VALUE_FAILED
;
847 _err
= rStoreDir
.next(iter
);
850 return RegError::NO_ERROR
;
853 RegError
ORegistry::loadKey(RegKeyHandle hKey
, const OUString
& regFileName
,
854 bool bWarnings
, bool bReport
)
856 ORegKey
* pKey
= static_cast< ORegKey
* >(hKey
);
858 std::unique_ptr
< ORegistry
> pReg (new ORegistry());
859 RegError _ret
= pReg
->initRegistry(regFileName
, RegAccessMode::READONLY
);
860 if (_ret
!= RegError::NO_ERROR
)
862 ORegKey
* pRootKey
= pReg
->getRootKey();
866 OStoreDirectory::iterator iter
;
867 OStoreDirectory
rStoreDir(pRootKey
->getStoreDir());
868 storeError _err
= rStoreDir
.first(iter
);
870 while (_err
== store_E_None
)
872 OUString
const keyName(iter
.m_pszName
, iter
.m_nLength
);
874 if (iter
.m_nAttrib
& STORE_ATTRIB_ISDIR
)
876 _ret
= loadAndSaveKeys(pKey
, pRootKey
, keyName
, 0, bWarnings
, bReport
);
880 _ret
= loadAndSaveValue(pKey
, pRootKey
, keyName
, 0, bWarnings
, bReport
);
883 if (_ret
== RegError::MERGE_ERROR
)
885 if (_ret
== RegError::MERGE_CONFLICT
&& bWarnings
)
888 _err
= rStoreDir
.next(iter
);
891 rStoreDir
= OStoreDirectory();
892 (void) pReg
->releaseKey(pRootKey
);
896 RegError
ORegistry::loadAndSaveValue(ORegKey
* pTargetKey
,
897 ORegKey
const * pSourceKey
,
898 const OUString
& valueName
,
904 RegValueType valueType
;
905 sal_uInt32 valueSize
;
907 storeAccessMode sourceAccess
= storeAccessMode::ReadWrite
;
908 OUString
sTargetPath(pTargetKey
->getName());
909 OUString
sSourcePath(pSourceKey
->getName());
911 if (pSourceKey
->isReadOnly())
913 sourceAccess
= storeAccessMode::ReadOnly
;
918 sTargetPath
= sSourcePath
.copy(nCut
);
921 if (sTargetPath
.getLength() > 1)
923 if (sSourcePath
.getLength() > 1)
924 sTargetPath
+= sSourcePath
;
926 sTargetPath
= sSourcePath
;
929 if (sTargetPath
.getLength() > 1) sTargetPath
+= ROOT
;
930 if (sSourcePath
.getLength() > 1) sSourcePath
+= ROOT
;
932 if (rValue
.create(pSourceKey
->getStoreFile(), sSourcePath
, valueName
, sourceAccess
))
934 return RegError::VALUE_NOT_EXISTS
;
937 std::vector
<sal_uInt8
> aBuffer(VALUE_HEADERSIZE
);
940 if (rValue
.readAt(0, aBuffer
.data(), VALUE_HEADERSIZE
, rwBytes
))
942 return RegError::INVALID_VALUE
;
944 if (rwBytes
!= VALUE_HEADERSIZE
)
946 return RegError::INVALID_VALUE
;
949 RegError _ret
= RegError::NO_ERROR
;
950 sal_uInt8 type
= aBuffer
[0];
951 valueType
= static_cast<RegValueType
>(type
);
952 readUINT32(aBuffer
.data() + VALUE_TYPEOFFSET
, valueSize
);
954 nSize
= VALUE_HEADERSIZE
+ valueSize
;
955 aBuffer
.resize(nSize
);
957 if (rValue
.readAt(0, aBuffer
.data(), nSize
, rwBytes
))
959 return RegError::INVALID_VALUE
;
961 if (rwBytes
!= nSize
)
963 return RegError::INVALID_VALUE
;
966 OStoreFile
rTargetFile(pTargetKey
->getStoreFile());
968 if (!rValue
.create(rTargetFile
, sTargetPath
, valueName
, storeAccessMode::ReadWrite
))
970 if (valueType
== RegValueType::BINARY
)
973 rValue
, sTargetPath
, valueSize
, aBuffer
.data() + VALUE_HEADEROFFSET
,
975 if (_ret
!= RegError::NO_ERROR
)
977 if (_ret
== RegError::MERGE_ERROR
||
978 (_ret
== RegError::MERGE_CONFLICT
&& bWarnings
))
989 if (rValue
.create(rTargetFile
, sTargetPath
, valueName
, storeAccessMode::Create
))
991 return RegError::INVALID_VALUE
;
993 if (rValue
.writeAt(0, aBuffer
.data(), nSize
, rwBytes
))
995 return RegError::INVALID_VALUE
;
998 if (rwBytes
!= nSize
)
1000 return RegError::INVALID_VALUE
;
1002 pTargetKey
->setModified();
1007 RegError
ORegistry::checkBlop(OStoreStream
& rValue
,
1008 const OUString
& sTargetPath
,
1009 sal_uInt32 srcValueSize
,
1010 sal_uInt8
const * pSrcBuffer
,
1013 RegistryTypeReader
reader(pSrcBuffer
, srcValueSize
);
1015 if (reader
.getTypeClass() == RT_TYPE_INVALID
)
1017 return RegError::INVALID_VALUE
;
1020 std::vector
<sal_uInt8
> aBuffer(VALUE_HEADERSIZE
);
1022 OString
targetPath(OUStringToOString(sTargetPath
, RTL_TEXTENCODING_UTF8
));
1024 if (!rValue
.readAt(0, aBuffer
.data(), VALUE_HEADERSIZE
, rwBytes
) &&
1025 (rwBytes
== VALUE_HEADERSIZE
))
1027 sal_uInt8 type
= aBuffer
[0];
1028 RegValueType valueType
= static_cast<RegValueType
>(type
);
1029 sal_uInt32 valueSize
;
1030 readUINT32(aBuffer
.data() + VALUE_TYPEOFFSET
, valueSize
);
1032 if (valueType
== RegValueType::BINARY
)
1034 aBuffer
.resize(valueSize
);
1035 if (!rValue
.readAt(VALUE_HEADEROFFSET
, aBuffer
.data(), valueSize
, rwBytes
) &&
1036 (rwBytes
== valueSize
))
1038 RegistryTypeReader
reader2(aBuffer
.data(), valueSize
);
1040 if ((reader
.getTypeClass() != reader2
.getTypeClass())
1041 || reader2
.getTypeClass() == RT_TYPE_INVALID
)
1045 fprintf(stdout
, "ERROR: values of blop from key \"%s\" has different types.\n",
1046 targetPath
.getStr());
1048 return RegError::MERGE_ERROR
;
1051 if (reader
.getTypeClass() == RT_TYPE_MODULE
)
1053 if (reader
.getFieldCount() > 0 &&
1054 reader2
.getFieldCount() > 0)
1056 mergeModuleValue(rValue
, reader
, reader2
);
1058 return RegError::NO_ERROR
;
1060 if (reader2
.getFieldCount() > 0)
1062 return RegError::NO_ERROR
;
1065 return RegError::MERGE_CONFLICT
;
1071 fprintf(stderr
, "WARNING: value of key \"%s\" already exists.\n",
1072 targetPath
.getStr());
1074 return RegError::MERGE_CONFLICT
;
1080 fprintf(stderr
, "ERROR: values of key \"%s\" contains bad data.\n",
1081 targetPath
.getStr());
1083 return RegError::MERGE_ERROR
;
1089 fprintf(stderr
, "ERROR: values of key \"%s\" has different types.\n",
1090 targetPath
.getStr());
1092 return RegError::MERGE_ERROR
;
1096 return RegError::INVALID_VALUE
;
1100 static sal_uInt32
checkTypeReaders(RegistryTypeReader
const & reader1
,
1101 RegistryTypeReader
const & reader2
,
1102 std::set
< OUString
>& nameSet
)
1105 for (sal_uInt32 i
=0 ; i
< reader1
.getFieldCount(); i
++)
1107 nameSet
.insert(reader1
.getFieldName(i
));
1110 for (sal_uInt32 i
=0 ; i
< reader2
.getFieldCount(); i
++)
1112 if (nameSet
.insert(reader2
.getFieldName(i
)).second
)
1118 RegError
ORegistry::mergeModuleValue(OStoreStream
& rTargetValue
,
1119 RegistryTypeReader
const & reader
,
1120 RegistryTypeReader
const & reader2
)
1122 std::set
< OUString
> nameSet
;
1123 sal_uInt32 count
= checkTypeReaders(reader
, reader2
, nameSet
);
1125 if (count
!= reader
.getFieldCount())
1127 sal_uInt16 index
= 0;
1129 RegistryTypeWriter
writer(reader
.getTypeClass(),
1130 reader
.getTypeName(),
1131 reader
.getSuperTypeName(),
1132 static_cast<sal_uInt16
>(count
));
1134 for (sal_uInt32 i
=0 ; i
< reader
.getFieldCount(); i
++)
1136 writer
.setFieldData(index
,
1137 reader
.getFieldName(i
),
1138 reader
.getFieldType(i
),
1139 reader
.getFieldDoku(i
),
1140 reader
.getFieldFileName(i
),
1141 reader
.getFieldAccess(i
),
1142 reader
.getFieldConstValue(i
));
1145 for (sal_uInt32 i
=0 ; i
< reader2
.getFieldCount(); i
++)
1147 if (nameSet
.find(reader2
.getFieldName(i
)) == nameSet
.end())
1149 writer
.setFieldData(index
,
1150 reader2
.getFieldName(i
),
1151 reader2
.getFieldType(i
),
1152 reader2
.getFieldDoku(i
),
1153 reader2
.getFieldFileName(i
),
1154 reader2
.getFieldAccess(i
),
1155 reader2
.getFieldConstValue(i
));
1160 const sal_uInt8
* pBlop
= writer
.getBlop();
1161 sal_uInt32 aBlopSize
= writer
.getBlopSize();
1163 sal_uInt8 type
= sal_uInt8(RegValueType::BINARY
);
1164 std::vector
<sal_uInt8
> aBuffer(VALUE_HEADERSIZE
+ aBlopSize
);
1166 memcpy(aBuffer
.data(), &type
, 1);
1167 writeUINT32(aBuffer
.data() + VALUE_TYPEOFFSET
, aBlopSize
);
1168 memcpy(aBuffer
.data() + VALUE_HEADEROFFSET
, pBlop
, aBlopSize
);
1171 if (rTargetValue
.writeAt(0, aBuffer
.data(), VALUE_HEADERSIZE
+aBlopSize
, rwBytes
))
1173 return RegError::INVALID_VALUE
;
1176 if (rwBytes
!= VALUE_HEADERSIZE
+aBlopSize
)
1178 return RegError::INVALID_VALUE
;
1181 return RegError::NO_ERROR
;
1184 RegError
ORegistry::loadAndSaveKeys(ORegKey
* pTargetKey
,
1185 ORegKey
* pSourceKey
,
1186 const OUString
& keyName
,
1191 RegError _ret
= RegError::NO_ERROR
;
1192 OUString
sRelPath(pSourceKey
->getName().copy(nCut
));
1195 if(pTargetKey
->getName().getLength() > 1)
1196 sFullPath
+= pTargetKey
->getName();
1197 sFullPath
+= sRelPath
;
1198 if (sRelPath
.getLength() > 1 || sFullPath
.isEmpty())
1201 OUString sFullKeyName
= sFullPath
+ keyName
;
1203 OStoreDirectory rStoreDir
;
1204 if (rStoreDir
.create(pTargetKey
->getStoreFile(), sFullPath
, keyName
, storeAccessMode::Create
))
1206 return RegError::CREATE_KEY_FAILED
;
1209 if (m_openKeyTable
.count(sFullKeyName
) > 0)
1211 m_openKeyTable
[sFullKeyName
]->setDeleted(false);
1214 ORegKey
* pTmpKey
= nullptr;
1215 _ret
= pSourceKey
->openKey(keyName
, reinterpret_cast<RegKeyHandle
*>(&pTmpKey
));
1216 if (_ret
!= RegError::NO_ERROR
)
1219 OStoreDirectory::iterator iter
;
1220 OStoreDirectory
rTmpStoreDir(pTmpKey
->getStoreDir());
1221 storeError _err
= rTmpStoreDir
.first(iter
);
1223 while (_err
== store_E_None
)
1225 OUString
const sName(iter
.m_pszName
, iter
.m_nLength
);
1227 if (iter
.m_nAttrib
& STORE_ATTRIB_ISDIR
)
1229 _ret
= loadAndSaveKeys(pTargetKey
, pTmpKey
,
1230 sName
, nCut
, bWarnings
, bReport
);
1233 _ret
= loadAndSaveValue(pTargetKey
, pTmpKey
,
1234 sName
, nCut
, bWarnings
, bReport
);
1237 if (_ret
== RegError::MERGE_ERROR
)
1239 if (_ret
== RegError::MERGE_CONFLICT
&& bWarnings
)
1242 _err
= rTmpStoreDir
.next(iter
);
1245 pSourceKey
->releaseKey(pTmpKey
);
1249 ORegKey
* ORegistry::getRootKey()
1251 m_openKeyTable
[ROOT
]->acquire();
1252 return m_openKeyTable
[ROOT
];
1255 RegError
ORegistry::dumpRegistry(RegKeyHandle hKey
) const
1257 ORegKey
*pKey
= static_cast<ORegKey
*>(hKey
);
1259 RegError _ret
= RegError::NO_ERROR
;
1260 OStoreDirectory::iterator iter
;
1261 OStoreDirectory
rStoreDir(pKey
->getStoreDir());
1262 storeError _err
= rStoreDir
.first(iter
);
1264 OString
regName(OUStringToOString(getName(), osl_getThreadTextEncoding()));
1265 OString
keyName(OUStringToOString(pKey
->getName(), RTL_TEXTENCODING_UTF8
));
1266 fprintf(stdout
, "Registry \"%s\":\n\n%s\n", regName
.getStr(), keyName
.getStr());
1268 while (_err
== store_E_None
)
1270 sName
= OUString(iter
.m_pszName
, iter
.m_nLength
);
1272 if (iter
.m_nAttrib
& STORE_ATTRIB_ISDIR
)
1274 _ret
= dumpKey(pKey
->getName(), sName
, 1);
1277 _ret
= dumpValue(pKey
->getName(), sName
, 1);
1280 if (_ret
!= RegError::NO_ERROR
)
1285 _err
= rStoreDir
.next(iter
);
1288 return RegError::NO_ERROR
;
1291 RegError
ORegistry::dumpValue(const OUString
& sPath
, const OUString
& sName
, sal_Int16 nSpc
) const
1293 OStoreStream rValue
;
1294 sal_uInt32 valueSize
;
1295 RegValueType valueType
;
1296 OUString
sFullPath(sPath
);
1298 storeAccessMode accessMode
= storeAccessMode::ReadWrite
;
1302 accessMode
= storeAccessMode::ReadOnly
;
1305 for (int i
= 0; i
< nSpc
; i
++) sIndent
+= " ";
1307 if (sFullPath
.getLength() > 1)
1311 if (rValue
.create(m_file
, sFullPath
, sName
, accessMode
))
1313 return RegError::VALUE_NOT_EXISTS
;
1316 std::vector
<sal_uInt8
> aBuffer(VALUE_HEADERSIZE
);
1319 if (rValue
.readAt(0, aBuffer
.data(), VALUE_HEADERSIZE
, rwBytes
))
1321 return RegError::INVALID_VALUE
;
1323 if (rwBytes
!= (VALUE_HEADERSIZE
))
1325 return RegError::INVALID_VALUE
;
1328 sal_uInt8 type
= aBuffer
[0];
1329 valueType
= static_cast<RegValueType
>(type
);
1330 readUINT32(aBuffer
.data() + VALUE_TYPEOFFSET
, valueSize
);
1332 aBuffer
.resize(valueSize
);
1333 if (rValue
.readAt(VALUE_HEADEROFFSET
, aBuffer
.data(), valueSize
, rwBytes
))
1335 return RegError::INVALID_VALUE
;
1337 if (rwBytes
!= valueSize
)
1339 return RegError::INVALID_VALUE
;
1342 const char* indent
= sIndent
.getStr();
1345 case RegValueType::NOT_DEFINED
:
1346 fprintf(stdout
, "%sValue: Type = VALUETYPE_NOT_DEFINED\n", indent
);
1348 case RegValueType::LONG
:
1350 fprintf(stdout
, "%sValue: Type = RegValueType::LONG\n", indent
);
1352 stdout
, "%s Size = %lu\n", indent
,
1353 sal::static_int_cast
< unsigned long >(valueSize
));
1354 fprintf(stdout
, "%s Data = ", indent
);
1357 readINT32(aBuffer
.data(), value
);
1358 fprintf(stdout
, "%ld\n", sal::static_int_cast
< long >(value
));
1361 case RegValueType::STRING
:
1363 char* value
= static_cast<char*>(std::malloc(valueSize
));
1364 readUtf8(aBuffer
.data(), value
, valueSize
);
1365 fprintf(stdout
, "%sValue: Type = RegValueType::STRING\n", indent
);
1367 stdout
, "%s Size = %lu\n", indent
,
1368 sal::static_int_cast
< unsigned long >(valueSize
));
1369 fprintf(stdout
, "%s Data = \"%s\"\n", indent
, value
);
1373 case RegValueType::UNICODE
:
1375 sal_uInt32 size
= (valueSize
/ 2) * sizeof(sal_Unicode
);
1376 fprintf(stdout
, "%sValue: Type = RegValueType::UNICODE\n", indent
);
1378 stdout
, "%s Size = %lu\n", indent
,
1379 sal::static_int_cast
< unsigned long >(valueSize
));
1380 fprintf(stdout
, "%s Data = ", indent
);
1382 std::unique_ptr
<sal_Unicode
[]> value(new sal_Unicode
[size
]);
1383 readString(aBuffer
.data(), value
.get(), size
);
1385 OString
uStr(value
.get(), rtl_ustr_getLength(value
.get()), RTL_TEXTENCODING_UTF8
);
1386 fprintf(stdout
, "L\"%s\"\n", uStr
.getStr());
1389 case RegValueType::BINARY
:
1391 fprintf(stdout
, "%sValue: Type = RegValueType::BINARY\n", indent
);
1393 stdout
, "%s Size = %lu\n", indent
,
1394 sal::static_int_cast
< unsigned long >(valueSize
));
1395 fprintf(stdout
, "%s Data = ", indent
);
1397 typereg::Reader(aBuffer
.data(), valueSize
),
1401 case RegValueType::LONGLIST
:
1403 sal_uInt32 offset
= 4; // initial 4 bytes for the size of the array
1406 readUINT32(aBuffer
.data(), len
);
1408 fprintf(stdout
, "%sValue: Type = RegValueType::LONGLIST\n", indent
);
1410 stdout
, "%s Size = %lu\n", indent
,
1411 sal::static_int_cast
< unsigned long >(valueSize
));
1413 stdout
, "%s Len = %lu\n", indent
,
1414 sal::static_int_cast
< unsigned long >(len
));
1415 fprintf(stdout
, "%s Data = ", indent
);
1417 sal_Int32 longValue
;
1418 for (sal_uInt32 i
=0; i
< len
; i
++)
1420 readINT32(aBuffer
.data() + offset
, longValue
);
1423 fprintf(stdout
, "%s ", indent
);
1426 stdout
, "%lu = %ld\n",
1427 sal::static_int_cast
< unsigned long >(i
),
1428 sal::static_int_cast
< long >(longValue
));
1429 offset
+= 4; // 4 Bytes for sal_Int32
1433 case RegValueType::STRINGLIST
:
1435 sal_uInt32 offset
= 4; // initial 4 bytes for the size of the array
1436 sal_uInt32 sLen
= 0;
1439 readUINT32(aBuffer
.data(), len
);
1441 fprintf(stdout
, "%sValue: Type = RegValueType::STRINGLIST\n", indent
);
1443 stdout
, "%s Size = %lu\n", indent
,
1444 sal::static_int_cast
< unsigned long >(valueSize
));
1446 stdout
, "%s Len = %lu\n", indent
,
1447 sal::static_int_cast
< unsigned long >(len
));
1448 fprintf(stdout
, "%s Data = ", indent
);
1450 for (sal_uInt32 i
=0; i
< len
; i
++)
1452 readUINT32(aBuffer
.data() + offset
, sLen
);
1454 offset
+= 4; // 4 bytes (sal_uInt32) for the string size
1456 char *pValue
= static_cast<char*>(std::malloc(sLen
));
1457 readUtf8(aBuffer
.data() + offset
, pValue
, sLen
);
1460 fprintf(stdout
, "%s ", indent
);
1463 stdout
, "%lu = \"%s\"\n",
1464 sal::static_int_cast
< unsigned long >(i
), pValue
);
1470 case RegValueType::UNICODELIST
:
1472 sal_uInt32 offset
= 4; // initial 4 bytes for the size of the array
1473 sal_uInt32 sLen
= 0;
1476 readUINT32(aBuffer
.data(), len
);
1478 fprintf(stdout
, "%sValue: Type = RegValueType::UNICODELIST\n", indent
);
1480 stdout
, "%s Size = %lu\n", indent
,
1481 sal::static_int_cast
< unsigned long >(valueSize
));
1483 stdout
, "%s Len = %lu\n", indent
,
1484 sal::static_int_cast
< unsigned long >(len
));
1485 fprintf(stdout
, "%s Data = ", indent
);
1488 for (sal_uInt32 i
=0; i
< len
; i
++)
1490 readUINT32(aBuffer
.data() + offset
, sLen
);
1492 offset
+= 4; // 4 bytes (sal_uInt32) for the string size
1494 sal_Unicode
*pValue
= static_cast<sal_Unicode
*>(std::malloc((sLen
/ 2) * sizeof(sal_Unicode
)));
1495 readString(aBuffer
.data() + offset
, pValue
, sLen
);
1498 fprintf(stdout
, "%s ", indent
);
1500 uStr
= OString(pValue
, rtl_ustr_getLength(pValue
), RTL_TEXTENCODING_UTF8
);
1502 stdout
, "%lu = L\"%s\"\n",
1503 sal::static_int_cast
< unsigned long >(i
),
1514 fprintf(stdout
, "\n");
1516 return RegError::NO_ERROR
;
1519 RegError
ORegistry::dumpKey(const OUString
& sPath
, const OUString
& sName
, sal_Int16 nSpace
) const
1521 OStoreDirectory rStoreDir
;
1522 OUString
sFullPath(sPath
);
1524 storeAccessMode accessMode
= storeAccessMode::ReadWrite
;
1525 RegError _ret
= RegError::NO_ERROR
;
1529 accessMode
= storeAccessMode::ReadOnly
;
1532 for (int i
= 0; i
< nSpace
; i
++) sIndent
+= " ";
1534 if (sFullPath
.getLength() > 1)
1537 storeError _err
= rStoreDir
.create(m_file
, sFullPath
, sName
, accessMode
);
1539 if (_err
== store_E_NotExists
)
1540 return RegError::KEY_NOT_EXISTS
;
1541 else if (_err
== store_E_WrongFormat
)
1542 return RegError::INVALID_KEY
;
1544 fprintf(stdout
, "%s/ %s\n", sIndent
.getStr(), OUStringToOString(sName
, RTL_TEXTENCODING_UTF8
).getStr());
1546 OUString
sSubPath(sFullPath
);
1550 OStoreDirectory::iterator iter
;
1552 _err
= rStoreDir
.first(iter
);
1554 while (_err
== store_E_None
)
1556 sSubName
= OUString(iter
.m_pszName
, iter
.m_nLength
);
1558 if (iter
.m_nAttrib
& STORE_ATTRIB_ISDIR
)
1560 _ret
= dumpKey(sSubPath
, sSubName
, nSpace
+2);
1563 _ret
= dumpValue(sSubPath
, sSubName
, nSpace
+2);
1566 if (_ret
!= RegError::NO_ERROR
)
1571 _err
= rStoreDir
.next(iter
);
1574 return RegError::NO_ERROR
;
1577 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */