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 .
22 #include <string_view>
24 #include "keyimpl.hxx"
26 #include "reflcnst.hxx"
27 #include <rtl/alloc.h>
28 #include <rtl/ustrbuf.hxx>
29 #include <osl/diagnose.h>
30 #include <sal/log.hxx>
33 using namespace store
;
35 namespace { char const VALUE_PREFIX
[] = "$VL_"; }
40 ORegKey::ORegKey(const OUString
& keyName
, ORegistry
* pReg
)
54 SAL_WARN_IF(m_refCount
!= 0, "registry", "registry::ORegKey::dtor(): refcount not zero.");
60 RegError
ORegKey::releaseKey(RegKeyHandle hKey
)
62 return m_pRegistry
->releaseKey(hKey
);
68 RegError
ORegKey::createKey(const OUString
& keyName
, RegKeyHandle
* phNewKey
)
70 return m_pRegistry
->createKey(this, keyName
, phNewKey
);
76 RegError
ORegKey::openKey(const OUString
& keyName
, RegKeyHandle
* phOpenKey
)
78 return m_pRegistry
->openKey(this, keyName
, phOpenKey
);
84 RegError
ORegKey::openSubKeys(const OUString
& keyName
, RegKeyHandle
** phOpenSubKeys
, sal_uInt32
* pnSubKeys
)
86 RegError _ret
= RegError::NO_ERROR
;
88 *phOpenSubKeys
= nullptr;
92 if ( !keyName
.isEmpty() )
94 _ret
= openKey(keyName
, reinterpret_cast<RegKeyHandle
*>(&pKey
));
95 if (_ret
!= RegError::NO_ERROR
)
99 sal_uInt32 nSubKeys
= pKey
->countSubKeys();
100 *pnSubKeys
= nSubKeys
;
103 pSubKeys
= static_cast<ORegKey
**>(rtl_allocateZeroMemory(nSubKeys
* sizeof(ORegKey
*)));
105 OStoreDirectory::iterator iter
;
106 OStoreDirectory
rStoreDir(pKey
->getStoreDir());
107 storeError _err
= rStoreDir
.first(iter
);
110 while ( _err
== store_E_None
)
112 if ( iter
.m_nAttrib
& STORE_ATTRIB_ISDIR
)
114 OUString
const sSubKeyName(iter
.m_pszName
, iter
.m_nLength
);
116 ORegKey
* pOpenSubKey
= nullptr;
117 _ret
= pKey
->openKey(sSubKeyName
, reinterpret_cast<RegKeyHandle
*>(&pOpenSubKey
));
118 if (_ret
!= RegError::NO_ERROR
)
120 *phOpenSubKeys
= nullptr;
122 std::free(pSubKeys
); // @@@ leaking 'pSubKeys[0...nSubkeys-1]'
123 return _ret
; // @@@ leaking 'pKey'
126 pSubKeys
[nSubKeys
] = pOpenSubKey
;
131 _err
= rStoreDir
.next(iter
);
134 *phOpenSubKeys
= reinterpret_cast<RegKeyHandle
*>(pSubKeys
);
135 if (!keyName
.isEmpty())
137 (void) releaseKey(pKey
);
139 return RegError::NO_ERROR
;
145 RegError
ORegKey::getKeyNames(const OUString
& keyName
,
146 rtl_uString
*** pSubKeyNames
,
147 sal_uInt32
* pnSubKeys
)
149 *pSubKeyNames
= nullptr;
152 ORegKey
* pKey
= this;
153 if (!keyName
.isEmpty())
155 RegError _ret
= openKey(keyName
, reinterpret_cast<RegKeyHandle
*>(&pKey
));
156 if (_ret
!= RegError::NO_ERROR
)
160 sal_uInt32 nSubKeys
= pKey
->countSubKeys();
161 *pnSubKeys
= nSubKeys
;
163 rtl_uString
** pSubKeys
164 = static_cast<rtl_uString
**>(rtl_allocateZeroMemory(nSubKeys
* sizeof(rtl_uString
*)));
166 OStoreDirectory::iterator iter
;
167 OStoreDirectory
rStoreDir(pKey
->getStoreDir());
168 storeError _err
= rStoreDir
.first(iter
);
172 while ( _err
== store_E_None
)
174 if ( iter
.m_nAttrib
& STORE_ATTRIB_ISDIR
)
176 OUString
const sSubKeyName(iter
.m_pszName
, iter
.m_nLength
);
178 OUString
sFullKeyName(pKey
->getName());
179 if (sFullKeyName
.getLength() > 1)
180 sFullKeyName
+= ORegistry::ROOT
;
181 sFullKeyName
+= sSubKeyName
;
183 rtl_uString_newFromString(&pSubKeys
[nSubKeys
], sFullKeyName
.pData
);
188 _err
= rStoreDir
.next(iter
);
191 *pSubKeyNames
= pSubKeys
;
192 if (!keyName
.isEmpty())
196 return RegError::NO_ERROR
;
202 RegError
ORegKey::closeKey(RegKeyHandle hKey
)
204 return m_pRegistry
->closeKey(hKey
);
210 RegError
ORegKey::deleteKey(const OUString
& keyName
)
212 return m_pRegistry
->deleteKey(this, keyName
);
218 RegError
ORegKey::getValueInfo(const OUString
& valueName
, RegValueType
* pValueType
, sal_uInt32
* pValueSize
) const
221 std::unique_ptr
<sal_uInt8
[]> pBuffer
;
222 storeAccessMode accessMode
= storeAccessMode::ReadWrite
;
224 if (m_pRegistry
->isReadOnly())
226 accessMode
= storeAccessMode::ReadOnly
;
229 OUString sImplValueName
= VALUE_PREFIX
+ valueName
;
231 REG_GUARD(m_pRegistry
->m_mutex
);
233 if ( rValue
.create(m_pRegistry
->getStoreFile(), m_name
+ ORegistry::ROOT
, sImplValueName
, accessMode
) )
235 *pValueType
= RegValueType::NOT_DEFINED
;
237 return RegError::VALUE_NOT_EXISTS
;
240 pBuffer
.reset(new sal_uInt8
[VALUE_HEADERSIZE
]);
242 sal_uInt32 readBytes
;
243 if ( rValue
.readAt(0, pBuffer
.get(), VALUE_HEADERSIZE
, readBytes
) )
245 return RegError::INVALID_VALUE
;
247 if (readBytes
!= VALUE_HEADERSIZE
)
249 return RegError::INVALID_VALUE
;
253 sal_uInt8 type
= pBuffer
[0];
254 readUINT32(pBuffer
.get()+VALUE_TYPEOFFSET
, size
);
256 *pValueType
= static_cast<RegValueType
>(type
);
257 if (*pValueType
> RegValueType::BINARY
)
259 pBuffer
.reset(new sal_uInt8
[4]);
260 rValue
.readAt(VALUE_HEADEROFFSET
, pBuffer
.get(), 4, readBytes
);
262 readUINT32(pBuffer
.get(), size
);
267 return RegError::NO_ERROR
;
273 RegError
ORegKey::setValue(const OUString
& valueName
, RegValueType vType
, RegValue value
, sal_uInt32 vSize
)
276 std::unique_ptr
<sal_uInt8
[]> pBuffer
;
278 if (m_pRegistry
->isReadOnly())
280 return RegError::REGISTRY_READONLY
;
283 if (vType
> RegValueType::BINARY
)
285 return RegError::INVALID_VALUE
;
288 OUString sImplValueName
= VALUE_PREFIX
+ valueName
;
290 REG_GUARD(m_pRegistry
->m_mutex
);
292 if ( rValue
.create(getStoreFile(), m_name
+ ORegistry::ROOT
, sImplValueName
, storeAccessMode::Create
) )
294 return RegError::SET_VALUE_FAILED
;
297 sal_uInt32 size
= vSize
;
299 sal_uInt8 type
= static_cast<sal_uInt8
>(vType
);
300 pBuffer
.reset(new sal_uInt8
[VALUE_HEADERSIZE
+ size
]);
301 memcpy(pBuffer
.get(), &type
, 1);
303 writeUINT32(pBuffer
.get()+VALUE_TYPEOFFSET
, size
);
307 case RegValueType::NOT_DEFINED
:
308 memcpy(pBuffer
.get()+VALUE_HEADEROFFSET
, value
, size
);
310 case RegValueType::LONG
:
311 writeINT32(pBuffer
.get()+VALUE_HEADEROFFSET
, *static_cast<sal_Int32
*>(value
));
313 case RegValueType::STRING
:
314 writeUtf8(pBuffer
.get()+VALUE_HEADEROFFSET
, static_cast<const char*>(value
));
316 case RegValueType::UNICODE
:
317 writeString(pBuffer
.get()+VALUE_HEADEROFFSET
, static_cast<const sal_Unicode
*>(value
));
319 case RegValueType::BINARY
:
320 memcpy(pBuffer
.get()+VALUE_HEADEROFFSET
, value
, size
);
327 sal_uInt32 writenBytes
;
328 if ( rValue
.writeAt(0, pBuffer
.get(), VALUE_HEADERSIZE
+size
, writenBytes
) )
330 return RegError::SET_VALUE_FAILED
;
332 if (writenBytes
!= (VALUE_HEADERSIZE
+size
))
334 return RegError::SET_VALUE_FAILED
;
338 return RegError::NO_ERROR
;
344 RegError
ORegKey::setLongListValue(const OUString
& valueName
, sal_Int32
const * pValueList
, sal_uInt32 len
)
347 std::unique_ptr
<sal_uInt8
[]> pBuffer
;
349 if (m_pRegistry
->isReadOnly())
351 return RegError::REGISTRY_READONLY
;
354 OUString sImplValueName
= VALUE_PREFIX
+ valueName
;
356 REG_GUARD(m_pRegistry
->m_mutex
);
358 if (rValue
.create(getStoreFile(), m_name
+ ORegistry::ROOT
, sImplValueName
, storeAccessMode::Create
) )
360 return RegError::SET_VALUE_FAILED
;
363 sal_uInt32 size
= 4; // 4 bytes (sal_uInt32) for the length
367 sal_uInt8 type
= sal_uInt8(RegValueType::LONGLIST
);
368 pBuffer
.reset(new sal_uInt8
[VALUE_HEADERSIZE
+ size
]);
369 memcpy(pBuffer
.get(), &type
, 1);
371 writeUINT32(pBuffer
.get()+VALUE_TYPEOFFSET
, size
);
372 writeUINT32(pBuffer
.get()+VALUE_HEADEROFFSET
, len
);
374 sal_uInt32 offset
= 4; // initial 4 bytes for the size of the array
376 for (sal_uInt32 i
=0; i
< len
; i
++)
378 writeINT32(pBuffer
.get()+VALUE_HEADEROFFSET
+offset
, pValueList
[i
]);
382 sal_uInt32 writenBytes
;
383 if ( rValue
.writeAt(0, pBuffer
.get(), VALUE_HEADERSIZE
+size
, writenBytes
) )
385 return RegError::SET_VALUE_FAILED
;
387 if (writenBytes
!= (VALUE_HEADEROFFSET
+size
))
389 return RegError::SET_VALUE_FAILED
;
393 return RegError::NO_ERROR
;
397 // setStringListValue
399 RegError
ORegKey::setStringListValue(const OUString
& valueName
, char** pValueList
, sal_uInt32 len
)
402 std::unique_ptr
<sal_uInt8
[]> pBuffer
;
404 if (m_pRegistry
->isReadOnly())
406 return RegError::REGISTRY_READONLY
;
409 OUString sImplValueName
= VALUE_PREFIX
+ valueName
;
411 REG_GUARD(m_pRegistry
->m_mutex
);
413 if (rValue
.create(getStoreFile(), m_name
+ ORegistry::ROOT
, sImplValueName
, storeAccessMode::Create
) )
415 return RegError::SET_VALUE_FAILED
;
418 sal_uInt32 size
= 4; // 4 bytes (sal_uInt32) for the length
421 for (i
=0; i
< len
; i
++)
423 size
+= 4 + strlen(pValueList
[i
]) + 1;
426 sal_uInt8 type
= sal_uInt8(RegValueType::STRINGLIST
);
427 pBuffer
.reset(new sal_uInt8
[VALUE_HEADERSIZE
+ size
]);
428 memcpy(pBuffer
.get(), &type
, 1);
430 writeUINT32(pBuffer
.get()+VALUE_TYPEOFFSET
, size
);
431 writeUINT32(pBuffer
.get()+VALUE_HEADEROFFSET
, len
);
433 sal_uInt32 offset
= 4; // initial 4 bytes for the size of the array;
436 for (i
=0; i
< len
; i
++)
438 sLen
= strlen(pValueList
[i
]) + 1;
439 writeUINT32(pBuffer
.get()+VALUE_HEADEROFFSET
+offset
, sLen
);
442 writeUtf8(pBuffer
.get()+VALUE_HEADEROFFSET
+offset
, pValueList
[i
]);
446 sal_uInt32 writenBytes
;
447 if ( rValue
.writeAt(0, pBuffer
.get(), VALUE_HEADERSIZE
+size
, writenBytes
) )
449 return RegError::SET_VALUE_FAILED
;
451 if (writenBytes
!= (VALUE_HEADERSIZE
+size
))
453 return RegError::SET_VALUE_FAILED
;
457 return RegError::NO_ERROR
;
461 // setUnicodeListValue
463 RegError
ORegKey::setUnicodeListValue(const OUString
& valueName
, sal_Unicode
** pValueList
, sal_uInt32 len
)
466 std::unique_ptr
<sal_uInt8
[]> pBuffer
;
468 if (m_pRegistry
->isReadOnly())
470 return RegError::REGISTRY_READONLY
;
473 OUString sImplValueName
= VALUE_PREFIX
+ valueName
;
475 REG_GUARD(m_pRegistry
->m_mutex
);
477 if (rValue
.create(getStoreFile(), m_name
+ ORegistry::ROOT
, sImplValueName
, storeAccessMode::Create
) )
479 return RegError::SET_VALUE_FAILED
;
482 sal_uInt32 size
= 4; // 4 bytes (sal_uInt32) for the length
485 for (i
=0; i
< len
; i
++)
487 size
+= 4 + ((rtl_ustr_getLength(pValueList
[i
]) +1) * 2);
490 sal_uInt8 type
= sal_uInt8(RegValueType::UNICODELIST
);
491 pBuffer
.reset(new sal_uInt8
[VALUE_HEADERSIZE
+ size
]);
492 memcpy(pBuffer
.get(), &type
, 1);
494 writeUINT32(pBuffer
.get()+VALUE_TYPEOFFSET
, size
);
495 writeUINT32(pBuffer
.get()+VALUE_HEADEROFFSET
, len
);
497 sal_uInt32 offset
= 4; // initial 4 bytes for the size of the array;
500 for (i
=0; i
< len
; i
++)
502 sLen
= (rtl_ustr_getLength(pValueList
[i
]) + 1) * 2;
503 writeUINT32(pBuffer
.get()+VALUE_HEADEROFFSET
+offset
, sLen
);
506 writeString(pBuffer
.get()+VALUE_HEADEROFFSET
+offset
, pValueList
[i
]);
510 sal_uInt32 writenBytes
;
511 if ( rValue
.writeAt(0, pBuffer
.get(), VALUE_HEADERSIZE
+size
, writenBytes
) )
513 return RegError::SET_VALUE_FAILED
;
515 if (writenBytes
!= (VALUE_HEADERSIZE
+size
))
517 return RegError::SET_VALUE_FAILED
;
521 return RegError::NO_ERROR
;
527 RegError
ORegKey::getValue(const OUString
& valueName
, RegValue value
) const
530 std::unique_ptr
<sal_uInt8
[]> pBuffer
;
531 RegValueType valueType
;
532 sal_uInt32 valueSize
;
533 storeAccessMode accessMode
= storeAccessMode::ReadWrite
;
535 if (m_pRegistry
->isReadOnly())
537 accessMode
= storeAccessMode::ReadOnly
;
540 OUString sImplValueName
= VALUE_PREFIX
+ valueName
;
542 REG_GUARD(m_pRegistry
->m_mutex
);
544 if (rValue
.create(getStoreFile(), m_name
+ ORegistry::ROOT
, sImplValueName
, accessMode
) )
546 return RegError::VALUE_NOT_EXISTS
;
549 pBuffer
.reset(new sal_uInt8
[VALUE_HEADERSIZE
]);
551 sal_uInt32 readBytes
;
552 if ( rValue
.readAt(0, pBuffer
.get(), VALUE_HEADERSIZE
, readBytes
) )
554 return RegError::INVALID_VALUE
;
556 if (readBytes
!= VALUE_HEADERSIZE
)
558 return RegError::INVALID_VALUE
;
561 sal_uInt8 type
= pBuffer
[0];
562 valueType
= static_cast<RegValueType
>(type
);
563 readUINT32(pBuffer
.get()+VALUE_TYPEOFFSET
, valueSize
);
565 if (valueType
> RegValueType::BINARY
)
567 return RegError::INVALID_VALUE
;
570 pBuffer
.reset(new sal_uInt8
[valueSize
]);
572 if ( rValue
.readAt(VALUE_HEADEROFFSET
, pBuffer
.get(), valueSize
, readBytes
) )
574 return RegError::INVALID_VALUE
;
576 if (readBytes
!= valueSize
)
578 return RegError::INVALID_VALUE
;
583 case RegValueType::NOT_DEFINED
:
584 memcpy(value
, pBuffer
.get(), valueSize
);
586 case RegValueType::LONG
:
587 readINT32(pBuffer
.get(), *static_cast<sal_Int32
*>(value
));
589 case RegValueType::STRING
:
590 readUtf8(pBuffer
.get(), static_cast<char*>(value
), valueSize
);
592 case RegValueType::UNICODE
:
593 readString(pBuffer
.get(), static_cast<sal_Unicode
*>(value
), valueSize
);
595 case RegValueType::BINARY
:
596 memcpy(value
, pBuffer
.get(), valueSize
);
598 // coverity[dead_error_begin] - following conditions exist to avoid compiler warning
599 case RegValueType::LONGLIST
:
600 case RegValueType::STRINGLIST
:
601 case RegValueType::UNICODELIST
:
602 memcpy(value
, pBuffer
.get(), valueSize
);
606 return RegError::NO_ERROR
;
612 RegError
ORegKey::getLongListValue(const OUString
& valueName
, sal_Int32
** pValueList
, sal_uInt32
* pLen
) const
615 std::unique_ptr
<sal_uInt8
[]> pBuffer
;
616 RegValueType valueType
;
617 sal_uInt32 valueSize
;
618 storeAccessMode accessMode
= storeAccessMode::ReadWrite
;
620 if (m_pRegistry
->isReadOnly())
622 accessMode
= storeAccessMode::ReadOnly
;
625 OUString sImplValueName
= VALUE_PREFIX
+ valueName
;
627 REG_GUARD(m_pRegistry
->m_mutex
);
629 if (rValue
.create(getStoreFile(), m_name
+ ORegistry::ROOT
, sImplValueName
, accessMode
) )
631 pValueList
= nullptr;
633 return RegError::VALUE_NOT_EXISTS
;
636 pBuffer
.reset(new sal_uInt8
[VALUE_HEADERSIZE
]);
638 sal_uInt32 readBytes
;
639 if ( rValue
.readAt(0, pBuffer
.get(), VALUE_HEADERSIZE
, readBytes
) )
641 pValueList
= nullptr;
643 return RegError::INVALID_VALUE
;
645 if (readBytes
!= VALUE_HEADERSIZE
)
647 pValueList
= nullptr;
649 return RegError::INVALID_VALUE
;
652 sal_uInt8 type
= pBuffer
[0];
653 valueType
= static_cast<RegValueType
>(type
);
655 if (valueType
!= RegValueType::LONGLIST
)
657 pValueList
= nullptr;
659 return RegError::INVALID_VALUE
;
662 readUINT32(pBuffer
.get()+VALUE_TYPEOFFSET
, valueSize
);
664 /* check for 'reasonable' value */
665 /* surely 10 millions entry in a registry list should be enough */
666 if(valueSize
> 40000000)
668 pValueList
= nullptr;
670 return RegError::INVALID_VALUE
;
672 pBuffer
.reset(new sal_uInt8
[valueSize
]);
674 if ( rValue
.readAt(VALUE_HEADEROFFSET
, pBuffer
.get(), valueSize
, readBytes
) )
676 pValueList
= nullptr;
678 return RegError::INVALID_VALUE
;
680 if (readBytes
!= valueSize
)
682 pValueList
= nullptr;
684 return RegError::INVALID_VALUE
;
688 readUINT32(pBuffer
.get(), len
);
690 /* make sure the declared size of the array is consistent with the amount of data we have read */
691 if(len
> (valueSize
- 4) / 4)
693 pValueList
= nullptr;
695 return RegError::INVALID_VALUE
;
698 sal_Int32
* pVList
= static_cast<sal_Int32
*>(rtl_allocateZeroMemory(len
* sizeof(sal_Int32
)));
700 sal_uInt32 offset
= 4; // initial 4 bytes for the size of the array;
702 for (sal_uInt32 i
= 0; i
< len
; i
++)
704 readINT32(pBuffer
.get()+offset
, pVList
[i
]);
708 *pValueList
= pVList
;
709 return RegError::NO_ERROR
;
713 // getStringListValue
715 RegError
ORegKey::getStringListValue(const OUString
& valueName
, char*** pValueList
, sal_uInt32
* pLen
) const
718 std::unique_ptr
<sal_uInt8
[]> pBuffer
;
719 RegValueType valueType
;
720 sal_uInt32 valueSize
;
721 storeAccessMode accessMode
= storeAccessMode::ReadWrite
;
723 if (m_pRegistry
->isReadOnly())
725 accessMode
= storeAccessMode::ReadOnly
;
728 OUString sImplValueName
= VALUE_PREFIX
+ valueName
;
730 REG_GUARD(m_pRegistry
->m_mutex
);
732 if ( rValue
.create(getStoreFile(), m_name
+ ORegistry::ROOT
, sImplValueName
, accessMode
) )
734 pValueList
= nullptr;
736 return RegError::VALUE_NOT_EXISTS
;
739 pBuffer
.reset(new sal_uInt8
[VALUE_HEADERSIZE
]);
741 sal_uInt32 readBytes
;
742 if ( rValue
.readAt(0, pBuffer
.get(), VALUE_HEADERSIZE
, readBytes
) )
744 pValueList
= nullptr;
746 return RegError::INVALID_VALUE
;
748 if (readBytes
!= VALUE_HEADERSIZE
)
750 pValueList
= nullptr;
752 return RegError::INVALID_VALUE
;
755 sal_uInt8 type
= pBuffer
[0];
756 valueType
= static_cast<RegValueType
>(type
);
758 if (valueType
!= RegValueType::STRINGLIST
)
760 pValueList
= nullptr;
762 return RegError::INVALID_VALUE
;
765 readUINT32(pBuffer
.get()+VALUE_TYPEOFFSET
, valueSize
);
767 pBuffer
.reset(new sal_uInt8
[valueSize
]);
769 if ( rValue
.readAt(VALUE_HEADEROFFSET
, pBuffer
.get(), valueSize
, readBytes
) )
771 pValueList
= nullptr;
773 return RegError::INVALID_VALUE
;
775 if (readBytes
!= valueSize
)
777 pValueList
= nullptr;
779 return RegError::INVALID_VALUE
;
783 readUINT32(pBuffer
.get(), len
);
786 char** pVList
= static_cast<char**>(rtl_allocateZeroMemory(len
* sizeof(char*)));
788 sal_uInt32 offset
= 4; // initial 4 bytes for the size of the array;
792 for (sal_uInt32 i
=0; i
< len
; i
++)
794 readUINT32(pBuffer
.get()+offset
, sLen
);
798 pValue
= static_cast<char*>(std::malloc(sLen
));
799 readUtf8(pBuffer
.get()+offset
, pValue
, sLen
);
805 *pValueList
= pVList
;
806 return RegError::NO_ERROR
;
810 // getUnicodeListValue
812 RegError
ORegKey::getUnicodeListValue(const OUString
& valueName
, sal_Unicode
*** pValueList
, sal_uInt32
* pLen
) const
815 std::unique_ptr
<sal_uInt8
[]> pBuffer
;
816 RegValueType valueType
;
817 sal_uInt32 valueSize
;
818 storeAccessMode accessMode
= storeAccessMode::ReadWrite
;
820 if (m_pRegistry
->isReadOnly())
822 accessMode
= storeAccessMode::ReadOnly
;
825 OUString sImplValueName
= VALUE_PREFIX
+ valueName
;
827 REG_GUARD(m_pRegistry
->m_mutex
);
829 if ( rValue
.create(getStoreFile(), m_name
+ ORegistry::ROOT
, sImplValueName
, accessMode
) )
831 pValueList
= nullptr;
833 return RegError::VALUE_NOT_EXISTS
;
836 pBuffer
.reset(new sal_uInt8
[VALUE_HEADERSIZE
]);
838 sal_uInt32 readBytes
;
839 if ( rValue
.readAt(0, pBuffer
.get(), VALUE_HEADERSIZE
, readBytes
) )
841 pValueList
= nullptr;
843 return RegError::INVALID_VALUE
;
845 if (readBytes
!= VALUE_HEADERSIZE
)
847 pValueList
= nullptr;
849 return RegError::INVALID_VALUE
;
852 sal_uInt8 type
= pBuffer
[0];
853 valueType
= static_cast<RegValueType
>(type
);
855 if (valueType
!= RegValueType::UNICODELIST
)
857 pValueList
= nullptr;
859 return RegError::INVALID_VALUE
;
862 readUINT32(pBuffer
.get()+VALUE_TYPEOFFSET
, valueSize
);
864 pBuffer
.reset(new sal_uInt8
[valueSize
]);
866 if ( rValue
.readAt(VALUE_HEADEROFFSET
, pBuffer
.get(), valueSize
, readBytes
) )
868 pValueList
= nullptr;
870 return RegError::INVALID_VALUE
;
872 if (readBytes
!= valueSize
)
874 pValueList
= nullptr;
876 return RegError::INVALID_VALUE
;
880 readUINT32(pBuffer
.get(), len
);
883 sal_Unicode
** pVList
= static_cast<sal_Unicode
**>(rtl_allocateZeroMemory(len
* sizeof(sal_Unicode
*)));
885 sal_uInt32 offset
= 4; // initial 4 bytes for the size of the array;
889 for (sal_uInt32 i
=0; i
< len
; i
++)
891 readUINT32(pBuffer
.get()+offset
, sLen
);
895 pValue
= static_cast<sal_Unicode
*>(std::malloc((sLen
/ 2) * sizeof(sal_Unicode
)));
896 readString(pBuffer
.get()+offset
, pValue
, sLen
);
902 *pValueList
= pVList
;
903 return RegError::NO_ERROR
;
907 RegError
ORegKey::getResolvedKeyName(const OUString
& keyName
,
908 OUString
& resolvedName
) const
910 if (keyName
.isEmpty())
911 return RegError::INVALID_KEYNAME
;
913 resolvedName
= getFullPath(keyName
);
914 return RegError::NO_ERROR
;
920 sal_uInt32
ORegKey::countSubKeys()
922 REG_GUARD(m_pRegistry
->m_mutex
);
924 OStoreDirectory::iterator iter
;
925 OStoreDirectory rStoreDir
= getStoreDir();
926 storeError _err
= rStoreDir
.first(iter
);
927 sal_uInt32 count
= 0;
929 while ( _err
== store_E_None
)
931 if ( iter
.m_nAttrib
& STORE_ATTRIB_ISDIR
)
936 _err
= rStoreDir
.next(iter
);
942 OStoreDirectory
ORegKey::getStoreDir() const
944 OStoreDirectory rStoreDir
;
946 OUString relativName
;
947 storeAccessMode accessMode
= storeAccessMode::ReadWrite
;
949 if ( m_name
== ORegistry::ROOT
)
955 fullPath
= m_name
.copy(0, m_name
.lastIndexOf('/') + 1);
956 relativName
= m_name
.copy(m_name
.lastIndexOf('/') + 1);
959 if (m_pRegistry
->isReadOnly())
961 accessMode
= storeAccessMode::ReadOnly
;
964 rStoreDir
.create(getStoreFile(), fullPath
, relativName
, accessMode
);
969 OUString
ORegKey::getFullPath(OUString
const & path
) const {
970 OSL_ASSERT(!m_name
.isEmpty() && !path
.isEmpty());
971 OUStringBuffer
b(32);
973 if (!b
.isEmpty() && b
[b
.getLength() - 1] == '/') {
974 if (path
[0] == '/') {
975 b
.append(std::u16string_view(path
).substr(1));
980 if (path
[0] != '/') {
985 return b
.makeStringAndClear();
988 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */