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 .
23 #include "keyimpl.hxx"
25 #include "reflcnst.hxx"
26 #include <rtl/alloc.h>
27 #include <rtl/ustrbuf.hxx>
28 #include <osl/diagnose.h>
29 #include <sal/log.hxx>
31 using namespace store
;
33 namespace { static char const VALUE_PREFIX
[] = "$VL_"; }
38 ORegKey::ORegKey(const OUString
& keyName
, ORegistry
* pReg
)
52 SAL_WARN_IF(m_refCount
!= 0, "registry", "registry::ORegKey::dtor(): refcount not zero.");
58 RegError
ORegKey::releaseKey(RegKeyHandle hKey
)
60 return m_pRegistry
->releaseKey(hKey
);
66 RegError
ORegKey::createKey(const OUString
& keyName
, RegKeyHandle
* phNewKey
)
68 return m_pRegistry
->createKey(this, keyName
, phNewKey
);
74 RegError
ORegKey::openKey(const OUString
& keyName
, RegKeyHandle
* phOpenKey
)
76 return m_pRegistry
->openKey(this, keyName
, phOpenKey
);
82 RegError
ORegKey::openSubKeys(const OUString
& keyName
, RegKeyHandle
** phOpenSubKeys
, sal_uInt32
* pnSubKeys
)
84 RegError _ret
= RegError::NO_ERROR
;
86 *phOpenSubKeys
= nullptr;
90 if ( !keyName
.isEmpty() )
92 _ret
= openKey(keyName
, reinterpret_cast<RegKeyHandle
*>(&pKey
));
93 if (_ret
!= RegError::NO_ERROR
)
97 sal_uInt32 nSubKeys
= pKey
->countSubKeys();
98 *pnSubKeys
= nSubKeys
;
101 pSubKeys
= static_cast<ORegKey
**>(rtl_allocateZeroMemory(nSubKeys
* sizeof(ORegKey
*)));
103 OStoreDirectory::iterator iter
;
104 OStoreDirectory
rStoreDir(pKey
->getStoreDir());
105 storeError _err
= rStoreDir
.first(iter
);
108 while ( _err
== store_E_None
)
110 if ( iter
.m_nAttrib
& STORE_ATTRIB_ISDIR
)
112 OUString
const sSubKeyName
= iter
.m_pszName
;
114 ORegKey
* pOpenSubKey
= nullptr;
115 _ret
= pKey
->openKey(sSubKeyName
, reinterpret_cast<RegKeyHandle
*>(&pOpenSubKey
));
116 if (_ret
!= RegError::NO_ERROR
)
118 *phOpenSubKeys
= nullptr;
120 rtl_freeMemory(pSubKeys
); // @@@ leaking 'pSubKeys[0...nSubkeys-1]'
121 return _ret
; // @@@ leaking 'pKey'
124 pSubKeys
[nSubKeys
] = pOpenSubKey
;
129 _err
= rStoreDir
.next(iter
);
132 *phOpenSubKeys
= reinterpret_cast<RegKeyHandle
*>(pSubKeys
);
133 if (!keyName
.isEmpty())
135 (void) releaseKey(pKey
);
137 return RegError::NO_ERROR
;
143 RegError
ORegKey::getKeyNames(const OUString
& keyName
,
144 rtl_uString
*** pSubKeyNames
,
145 sal_uInt32
* pnSubKeys
)
147 RegError _ret
= RegError::NO_ERROR
;
149 *pSubKeyNames
= nullptr;
152 ORegKey
* pKey
= this;
153 if (!keyName
.isEmpty())
155 _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
= nullptr;
164 pSubKeys
= 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
;
178 OUString
sFullKeyName(pKey
->getName());
179 if (sFullKeyName
.getLength() > 1)
180 sFullKeyName
+= m_pRegistry
->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
222 storeAccessMode accessMode
= storeAccessMode::ReadWrite
;
224 if (m_pRegistry
->isReadOnly())
226 accessMode
= storeAccessMode::ReadOnly
;
229 OUString
sImplValueName( VALUE_PREFIX
);
230 sImplValueName
+= valueName
;
232 REG_GUARD(m_pRegistry
->m_mutex
);
234 if ( rValue
.create(m_pRegistry
->getStoreFile(), m_name
+ m_pRegistry
->ROOT
, sImplValueName
, accessMode
) )
236 *pValueType
= RegValueType::NOT_DEFINED
;
238 return RegError::VALUE_NOT_EXISTS
;
241 pBuffer
= static_cast<sal_uInt8
*>(rtl_allocateMemory(VALUE_HEADERSIZE
));
243 sal_uInt32 readBytes
;
244 if ( rValue
.readAt(0, pBuffer
, VALUE_HEADERSIZE
, readBytes
) )
246 rtl_freeMemory(pBuffer
);
247 return RegError::INVALID_VALUE
;
249 if (readBytes
!= VALUE_HEADERSIZE
)
251 rtl_freeMemory(pBuffer
);
252 return RegError::INVALID_VALUE
;
256 sal_uInt8 type
= *pBuffer
;
257 readUINT32(pBuffer
+VALUE_TYPEOFFSET
, size
);
259 *pValueType
= static_cast<RegValueType
>(type
);
260 // if (*pValueType == RegValueType::UNICODE)
262 // *pValueSize = (size / 2) * sizeof(sal_Unicode);
265 if (*pValueType
> RegValueType::BINARY
)
267 rtl_freeMemory(pBuffer
);
268 pBuffer
= static_cast<sal_uInt8
*>(rtl_allocateMemory(4));
269 rValue
.readAt(VALUE_HEADEROFFSET
, pBuffer
, 4, readBytes
);
271 readUINT32(pBuffer
, size
);
277 rtl_freeMemory(pBuffer
);
278 return RegError::NO_ERROR
;
284 RegError
ORegKey::setValue(const OUString
& valueName
, RegValueType vType
, RegValue value
, sal_uInt32 vSize
)
289 if (m_pRegistry
->isReadOnly())
291 return RegError::REGISTRY_READONLY
;
294 if (vType
> RegValueType::BINARY
)
296 return RegError::INVALID_VALUE
;
299 OUString
sImplValueName( VALUE_PREFIX
);
300 sImplValueName
+= valueName
;
302 REG_GUARD(m_pRegistry
->m_mutex
);
304 if ( rValue
.create(getStoreFile(), m_name
+ m_pRegistry
->ROOT
, sImplValueName
, storeAccessMode::Create
) )
306 return RegError::SET_VALUE_FAILED
;
309 sal_uInt32 size
= vSize
;
311 sal_uInt8 type
= static_cast<sal_uInt8
>(vType
);
312 pBuffer
= static_cast<sal_uInt8
*>(rtl_allocateMemory(VALUE_HEADERSIZE
+ size
));
313 memcpy(pBuffer
, &type
, 1);
315 writeUINT32(pBuffer
+VALUE_TYPEOFFSET
, size
);
319 case RegValueType::NOT_DEFINED
:
320 memcpy(pBuffer
+VALUE_HEADEROFFSET
, value
, size
);
322 case RegValueType::LONG
:
323 writeINT32(pBuffer
+VALUE_HEADEROFFSET
, *static_cast<sal_Int32
*>(value
));
325 case RegValueType::STRING
:
326 writeUtf8(pBuffer
+VALUE_HEADEROFFSET
, static_cast<const sal_Char
*>(value
));
328 case RegValueType::UNICODE
:
329 writeString(pBuffer
+VALUE_HEADEROFFSET
, static_cast<const sal_Unicode
*>(value
));
331 case RegValueType::BINARY
:
332 memcpy(pBuffer
+VALUE_HEADEROFFSET
, value
, size
);
339 sal_uInt32 writenBytes
;
340 if ( rValue
.writeAt(0, pBuffer
, VALUE_HEADERSIZE
+size
, writenBytes
) )
342 rtl_freeMemory(pBuffer
);
343 return RegError::SET_VALUE_FAILED
;
345 if (writenBytes
!= (VALUE_HEADERSIZE
+size
))
347 rtl_freeMemory(pBuffer
);
348 return RegError::SET_VALUE_FAILED
;
352 rtl_freeMemory(pBuffer
);
353 return RegError::NO_ERROR
;
359 RegError
ORegKey::setLongListValue(const OUString
& valueName
, sal_Int32
const * pValueList
, sal_uInt32 len
)
364 if (m_pRegistry
->isReadOnly())
366 return RegError::REGISTRY_READONLY
;
369 OUString
sImplValueName( VALUE_PREFIX
);
370 sImplValueName
+= valueName
;
372 REG_GUARD(m_pRegistry
->m_mutex
);
374 if (rValue
.create(getStoreFile(), m_name
+ m_pRegistry
->ROOT
, sImplValueName
, storeAccessMode::Create
) )
376 return RegError::SET_VALUE_FAILED
;
379 sal_uInt32 size
= 4; // 4 bytes (sal_uInt32) for the length
383 sal_uInt8 type
= sal_uInt8(RegValueType::LONGLIST
);
384 pBuffer
= static_cast<sal_uInt8
*>(rtl_allocateMemory(VALUE_HEADERSIZE
+ size
));
385 memcpy(pBuffer
, &type
, 1);
387 writeUINT32(pBuffer
+VALUE_TYPEOFFSET
, size
);
388 writeUINT32(pBuffer
+VALUE_HEADEROFFSET
, len
);
390 sal_uInt32 offset
= 4; // initial 4 bytes for the size of the array
392 for (sal_uInt32 i
=0; i
< len
; i
++)
394 writeINT32(pBuffer
+VALUE_HEADEROFFSET
+offset
, pValueList
[i
]);
398 sal_uInt32 writenBytes
;
399 if ( rValue
.writeAt(0, pBuffer
, VALUE_HEADERSIZE
+size
, writenBytes
) )
401 rtl_freeMemory(pBuffer
);
402 return RegError::SET_VALUE_FAILED
;
404 if (writenBytes
!= (VALUE_HEADEROFFSET
+size
))
406 rtl_freeMemory(pBuffer
);
407 return RegError::SET_VALUE_FAILED
;
411 rtl_freeMemory(pBuffer
);
412 return RegError::NO_ERROR
;
416 // setStringListValue
418 RegError
ORegKey::setStringListValue(const OUString
& valueName
, sal_Char
** pValueList
, sal_uInt32 len
)
423 if (m_pRegistry
->isReadOnly())
425 return RegError::REGISTRY_READONLY
;
428 OUString
sImplValueName( VALUE_PREFIX
);
429 sImplValueName
+= valueName
;
431 REG_GUARD(m_pRegistry
->m_mutex
);
433 if (rValue
.create(getStoreFile(), m_name
+ m_pRegistry
->ROOT
, sImplValueName
, storeAccessMode::Create
) )
435 return RegError::SET_VALUE_FAILED
;
438 sal_uInt32 size
= 4; // 4 bytes (sal_uInt32) for the length
441 for (i
=0; i
< len
; i
++)
443 size
+= 4 + strlen(pValueList
[i
]) + 1;
446 sal_uInt8 type
= sal_uInt8(RegValueType::STRINGLIST
);
447 pBuffer
= static_cast<sal_uInt8
*>(rtl_allocateMemory(VALUE_HEADERSIZE
+ size
));
448 memcpy(pBuffer
, &type
, 1);
450 writeUINT32(pBuffer
+VALUE_TYPEOFFSET
, size
);
451 writeUINT32(pBuffer
+VALUE_HEADEROFFSET
, len
);
453 sal_uInt32 offset
= 4; // initial 4 bytes for the size of the array;
456 for (i
=0; i
< len
; i
++)
458 sLen
= strlen(pValueList
[i
]) + 1;
459 writeUINT32(pBuffer
+VALUE_HEADEROFFSET
+offset
, sLen
);
462 writeUtf8(pBuffer
+VALUE_HEADEROFFSET
+offset
, pValueList
[i
]);
466 sal_uInt32 writenBytes
;
467 if ( rValue
.writeAt(0, pBuffer
, VALUE_HEADERSIZE
+size
, writenBytes
) )
469 rtl_freeMemory(pBuffer
);
470 return RegError::SET_VALUE_FAILED
;
472 if (writenBytes
!= (VALUE_HEADERSIZE
+size
))
474 rtl_freeMemory(pBuffer
);
475 return RegError::SET_VALUE_FAILED
;
479 rtl_freeMemory(pBuffer
);
480 return RegError::NO_ERROR
;
484 // setUnicodeListValue
486 RegError
ORegKey::setUnicodeListValue(const OUString
& valueName
, sal_Unicode
** pValueList
, sal_uInt32 len
)
491 if (m_pRegistry
->isReadOnly())
493 return RegError::REGISTRY_READONLY
;
496 OUString
sImplValueName( VALUE_PREFIX
);
497 sImplValueName
+= valueName
;
499 REG_GUARD(m_pRegistry
->m_mutex
);
501 if (rValue
.create(getStoreFile(), m_name
+ m_pRegistry
->ROOT
, sImplValueName
, storeAccessMode::Create
) )
503 return RegError::SET_VALUE_FAILED
;
506 sal_uInt32 size
= 4; // 4 bytes (sal_uInt32) for the length
509 for (i
=0; i
< len
; i
++)
511 size
+= 4 + ((rtl_ustr_getLength(pValueList
[i
]) +1) * 2);
514 sal_uInt8 type
= sal_uInt8(RegValueType::UNICODELIST
);
515 pBuffer
= static_cast<sal_uInt8
*>(rtl_allocateMemory(VALUE_HEADERSIZE
+ size
));
516 memcpy(pBuffer
, &type
, 1);
518 writeUINT32(pBuffer
+VALUE_TYPEOFFSET
, size
);
519 writeUINT32(pBuffer
+VALUE_HEADEROFFSET
, len
);
521 sal_uInt32 offset
= 4; // initial 4 bytes for the size of the array;
524 for (i
=0; i
< len
; i
++)
526 sLen
= (rtl_ustr_getLength(pValueList
[i
]) + 1) * 2;
527 writeUINT32(pBuffer
+VALUE_HEADEROFFSET
+offset
, sLen
);
530 writeString(pBuffer
+VALUE_HEADEROFFSET
+offset
, pValueList
[i
]);
534 sal_uInt32 writenBytes
;
535 if ( rValue
.writeAt(0, pBuffer
, VALUE_HEADERSIZE
+size
, writenBytes
) )
537 rtl_freeMemory(pBuffer
);
538 return RegError::SET_VALUE_FAILED
;
540 if (writenBytes
!= (VALUE_HEADERSIZE
+size
))
542 rtl_freeMemory(pBuffer
);
543 return RegError::SET_VALUE_FAILED
;
547 rtl_freeMemory(pBuffer
);
548 return RegError::NO_ERROR
;
554 RegError
ORegKey::getValue(const OUString
& valueName
, RegValue value
) const
558 RegValueType valueType
;
559 sal_uInt32 valueSize
;
560 storeAccessMode accessMode
= storeAccessMode::ReadWrite
;
562 if (m_pRegistry
->isReadOnly())
564 accessMode
= storeAccessMode::ReadOnly
;
567 OUString
sImplValueName( VALUE_PREFIX
);
568 sImplValueName
+= valueName
;
570 REG_GUARD(m_pRegistry
->m_mutex
);
572 if (rValue
.create(getStoreFile(), m_name
+ m_pRegistry
->ROOT
, sImplValueName
, accessMode
) )
574 return RegError::VALUE_NOT_EXISTS
;
577 pBuffer
= static_cast<sal_uInt8
*>(rtl_allocateMemory(VALUE_HEADERSIZE
));
579 sal_uInt32 readBytes
;
580 if ( rValue
.readAt(0, pBuffer
, VALUE_HEADERSIZE
, readBytes
) )
582 rtl_freeMemory(pBuffer
);
583 return RegError::INVALID_VALUE
;
585 if (readBytes
!= VALUE_HEADERSIZE
)
587 rtl_freeMemory(pBuffer
);
588 return RegError::INVALID_VALUE
;
591 sal_uInt8 type
= *pBuffer
;
592 valueType
= static_cast<RegValueType
>(type
);
593 readUINT32(pBuffer
+VALUE_TYPEOFFSET
, valueSize
);
595 rtl_freeMemory(pBuffer
);
597 if (valueType
> RegValueType::BINARY
)
599 return RegError::INVALID_VALUE
;
602 pBuffer
= static_cast<sal_uInt8
*>(rtl_allocateMemory(valueSize
));
604 if ( rValue
.readAt(VALUE_HEADEROFFSET
, pBuffer
, valueSize
, readBytes
) )
606 rtl_freeMemory(pBuffer
);
607 return RegError::INVALID_VALUE
;
609 if (readBytes
!= valueSize
)
611 rtl_freeMemory(pBuffer
);
612 return RegError::INVALID_VALUE
;
617 case RegValueType::NOT_DEFINED
:
618 memcpy(value
, pBuffer
, valueSize
);
620 case RegValueType::LONG
:
621 readINT32(pBuffer
, *static_cast<sal_Int32
*>(value
));
623 case RegValueType::STRING
:
624 readUtf8(pBuffer
, static_cast<sal_Char
*>(value
), valueSize
);
626 case RegValueType::UNICODE
:
627 readString(pBuffer
, static_cast<sal_Unicode
*>(value
), valueSize
);
629 case RegValueType::BINARY
:
630 memcpy(value
, pBuffer
, valueSize
);
632 // coverity[dead_error_begin] - following conditions exist to avoid compiler warning
633 case RegValueType::LONGLIST
:
634 case RegValueType::STRINGLIST
:
635 case RegValueType::UNICODELIST
:
636 memcpy(value
, pBuffer
, valueSize
);
641 rtl_freeMemory(pBuffer
);
642 return RegError::NO_ERROR
;
648 RegError
ORegKey::getLongListValue(const OUString
& valueName
, sal_Int32
** pValueList
, sal_uInt32
* pLen
) const
652 RegValueType valueType
;
653 sal_uInt32 valueSize
;
654 storeAccessMode accessMode
= storeAccessMode::ReadWrite
;
656 if (m_pRegistry
->isReadOnly())
658 accessMode
= storeAccessMode::ReadOnly
;
661 OUString
sImplValueName( VALUE_PREFIX
);
662 sImplValueName
+= valueName
;
664 REG_GUARD(m_pRegistry
->m_mutex
);
666 if (rValue
.create(getStoreFile(), m_name
+ m_pRegistry
->ROOT
, sImplValueName
, accessMode
) )
668 pValueList
= nullptr;
670 return RegError::VALUE_NOT_EXISTS
;
673 pBuffer
= static_cast<sal_uInt8
*>(rtl_allocateMemory(VALUE_HEADERSIZE
));
675 sal_uInt32 readBytes
;
676 if ( rValue
.readAt(0, pBuffer
, VALUE_HEADERSIZE
, readBytes
) )
678 pValueList
= nullptr;
680 rtl_freeMemory(pBuffer
);
681 return RegError::INVALID_VALUE
;
683 if (readBytes
!= VALUE_HEADERSIZE
)
685 pValueList
= nullptr;
687 rtl_freeMemory(pBuffer
);
688 return RegError::INVALID_VALUE
;
691 sal_uInt8 type
= *pBuffer
;
692 valueType
= static_cast<RegValueType
>(type
);
694 if (valueType
!= RegValueType::LONGLIST
)
696 pValueList
= nullptr;
698 rtl_freeMemory(pBuffer
);
699 return RegError::INVALID_VALUE
;
702 readUINT32(pBuffer
+VALUE_TYPEOFFSET
, valueSize
);
704 rtl_freeMemory(pBuffer
);
706 /* check for 'reasonable' value */
707 /* surely 10 millions entry in a registry list should be enough */
708 if(valueSize
> 40000000)
710 pValueList
= nullptr;
712 rtl_freeMemory(pBuffer
);
713 return RegError::INVALID_VALUE
;
715 pBuffer
= static_cast<sal_uInt8
*>(rtl_allocateMemory(valueSize
));
717 if ( rValue
.readAt(VALUE_HEADEROFFSET
, pBuffer
, valueSize
, readBytes
) )
719 pValueList
= nullptr;
721 rtl_freeMemory(pBuffer
);
722 return RegError::INVALID_VALUE
;
724 if (readBytes
!= valueSize
)
726 pValueList
= nullptr;
728 rtl_freeMemory(pBuffer
);
729 return RegError::INVALID_VALUE
;
733 readUINT32(pBuffer
, len
);
735 /* make sure the declared size of the arry is consistent with the amount of data we have read */
736 if(len
> (valueSize
- 4) / 4)
738 pValueList
= nullptr;
740 rtl_freeMemory(pBuffer
);
741 return RegError::INVALID_VALUE
;
744 sal_Int32
* pVList
= static_cast<sal_Int32
*>(rtl_allocateZeroMemory(len
* sizeof(sal_Int32
)));
746 sal_uInt32 offset
= 4; // initial 4 bytes for the size of the array;
748 for (sal_uInt32 i
= 0; i
< len
; i
++)
750 readINT32(pBuffer
+offset
, pVList
[i
]);
754 *pValueList
= pVList
;
755 rtl_freeMemory(pBuffer
);
756 return RegError::NO_ERROR
;
760 // getStringListValue
762 RegError
ORegKey::getStringListValue(const OUString
& valueName
, sal_Char
*** pValueList
, sal_uInt32
* pLen
) const
766 RegValueType valueType
;
767 sal_uInt32 valueSize
;
768 storeAccessMode accessMode
= storeAccessMode::ReadWrite
;
770 if (m_pRegistry
->isReadOnly())
772 accessMode
= storeAccessMode::ReadOnly
;
775 OUString
sImplValueName( VALUE_PREFIX
);
776 sImplValueName
+= valueName
;
778 REG_GUARD(m_pRegistry
->m_mutex
);
780 if ( rValue
.create(getStoreFile(), m_name
+ m_pRegistry
->ROOT
, sImplValueName
, accessMode
) )
782 pValueList
= nullptr;
784 return RegError::VALUE_NOT_EXISTS
;
787 pBuffer
= static_cast<sal_uInt8
*>(rtl_allocateMemory(VALUE_HEADERSIZE
));
789 sal_uInt32 readBytes
;
790 if ( rValue
.readAt(0, pBuffer
, VALUE_HEADERSIZE
, readBytes
) )
792 pValueList
= nullptr;
794 rtl_freeMemory(pBuffer
);
795 return RegError::INVALID_VALUE
;
797 if (readBytes
!= VALUE_HEADERSIZE
)
799 pValueList
= nullptr;
801 rtl_freeMemory(pBuffer
);
802 return RegError::INVALID_VALUE
;
805 sal_uInt8 type
= *pBuffer
;
806 valueType
= static_cast<RegValueType
>(type
);
808 if (valueType
!= RegValueType::STRINGLIST
)
810 pValueList
= nullptr;
812 rtl_freeMemory(pBuffer
);
813 return RegError::INVALID_VALUE
;
816 readUINT32(pBuffer
+VALUE_TYPEOFFSET
, valueSize
);
818 rtl_freeMemory(pBuffer
);
820 pBuffer
= static_cast<sal_uInt8
*>(rtl_allocateMemory(valueSize
));
822 if ( rValue
.readAt(VALUE_HEADEROFFSET
, pBuffer
, valueSize
, readBytes
) )
824 pValueList
= nullptr;
826 rtl_freeMemory(pBuffer
);
827 return RegError::INVALID_VALUE
;
829 if (readBytes
!= valueSize
)
831 pValueList
= nullptr;
833 rtl_freeMemory(pBuffer
);
834 return RegError::INVALID_VALUE
;
838 readUINT32(pBuffer
, len
);
841 sal_Char
** pVList
= static_cast<sal_Char
**>(rtl_allocateZeroMemory(len
* sizeof(sal_Char
*)));
843 sal_uInt32 offset
= 4; // initial 4 bytes for the size of the array;
847 for (sal_uInt32 i
=0; i
< len
; i
++)
849 readUINT32(pBuffer
+offset
, sLen
);
853 pValue
= static_cast<sal_Char
*>(rtl_allocateMemory(sLen
));
854 readUtf8(pBuffer
+offset
, pValue
, sLen
);
860 *pValueList
= pVList
;
861 rtl_freeMemory(pBuffer
);
862 return RegError::NO_ERROR
;
866 // getUnicodeListValue
868 RegError
ORegKey::getUnicodeListValue(const OUString
& valueName
, sal_Unicode
*** pValueList
, sal_uInt32
* pLen
) const
872 RegValueType valueType
;
873 sal_uInt32 valueSize
;
874 storeAccessMode accessMode
= storeAccessMode::ReadWrite
;
876 if (m_pRegistry
->isReadOnly())
878 accessMode
= storeAccessMode::ReadOnly
;
881 OUString
sImplValueName( VALUE_PREFIX
);
882 sImplValueName
+= valueName
;
884 REG_GUARD(m_pRegistry
->m_mutex
);
886 if ( rValue
.create(getStoreFile(), m_name
+ m_pRegistry
->ROOT
, sImplValueName
, accessMode
) )
888 pValueList
= nullptr;
890 return RegError::VALUE_NOT_EXISTS
;
893 pBuffer
= static_cast<sal_uInt8
*>(rtl_allocateMemory(VALUE_HEADERSIZE
));
895 sal_uInt32 readBytes
;
896 if ( rValue
.readAt(0, pBuffer
, VALUE_HEADERSIZE
, readBytes
) )
898 pValueList
= nullptr;
900 rtl_freeMemory(pBuffer
);
901 return RegError::INVALID_VALUE
;
903 if (readBytes
!= VALUE_HEADERSIZE
)
905 pValueList
= nullptr;
907 rtl_freeMemory(pBuffer
);
908 return RegError::INVALID_VALUE
;
911 sal_uInt8 type
= *pBuffer
;
912 valueType
= static_cast<RegValueType
>(type
);
914 if (valueType
!= RegValueType::UNICODELIST
)
916 pValueList
= nullptr;
918 rtl_freeMemory(pBuffer
);
919 return RegError::INVALID_VALUE
;
922 readUINT32(pBuffer
+VALUE_TYPEOFFSET
, valueSize
);
924 rtl_freeMemory(pBuffer
);
926 pBuffer
= static_cast<sal_uInt8
*>(rtl_allocateMemory(valueSize
));
928 if ( rValue
.readAt(VALUE_HEADEROFFSET
, pBuffer
, valueSize
, readBytes
) )
930 pValueList
= nullptr;
932 rtl_freeMemory(pBuffer
);
933 return RegError::INVALID_VALUE
;
935 if (readBytes
!= valueSize
)
937 pValueList
= nullptr;
939 rtl_freeMemory(pBuffer
);
940 return RegError::INVALID_VALUE
;
944 readUINT32(pBuffer
, len
);
947 sal_Unicode
** pVList
= static_cast<sal_Unicode
**>(rtl_allocateZeroMemory(len
* sizeof(sal_Unicode
*)));
949 sal_uInt32 offset
= 4; // initial 4 bytes for the size of the array;
953 for (sal_uInt32 i
=0; i
< len
; i
++)
955 readUINT32(pBuffer
+offset
, sLen
);
959 pValue
= static_cast<sal_Unicode
*>(rtl_allocateMemory((sLen
/ 2) * sizeof(sal_Unicode
)));
960 readString(pBuffer
+offset
, pValue
, sLen
);
966 *pValueList
= pVList
;
967 rtl_freeMemory(pBuffer
);
968 return RegError::NO_ERROR
;
972 RegError
ORegKey::getResolvedKeyName(const OUString
& keyName
,
973 OUString
& resolvedName
) const
975 if (keyName
.isEmpty())
976 return RegError::INVALID_KEYNAME
;
978 resolvedName
= getFullPath(keyName
);
979 return RegError::NO_ERROR
;
985 sal_uInt32
ORegKey::countSubKeys()
987 REG_GUARD(m_pRegistry
->m_mutex
);
989 OStoreDirectory::iterator iter
;
990 OStoreDirectory rStoreDir
= getStoreDir();
991 storeError _err
= rStoreDir
.first(iter
);
992 sal_uInt32 count
= 0;
994 while ( _err
== store_E_None
)
996 if ( iter
.m_nAttrib
& STORE_ATTRIB_ISDIR
)
1001 _err
= rStoreDir
.next(iter
);
1007 OStoreDirectory
ORegKey::getStoreDir() const
1009 OStoreDirectory rStoreDir
;
1011 OUString relativName
;
1012 storeAccessMode accessMode
= storeAccessMode::ReadWrite
;
1014 if ( m_name
== m_pRegistry
->ROOT
)
1017 relativName
.clear();
1020 fullPath
= m_name
.copy(0, m_name
.lastIndexOf('/') + 1);
1021 relativName
= m_name
.copy(m_name
.lastIndexOf('/') + 1);
1024 if (m_pRegistry
->isReadOnly())
1026 accessMode
= storeAccessMode::ReadOnly
;
1029 rStoreDir
.create(getStoreFile(), fullPath
, relativName
, accessMode
);
1034 OUString
ORegKey::getFullPath(OUString
const & path
) const {
1035 OSL_ASSERT(!m_name
.isEmpty() && !path
.isEmpty());
1036 OUStringBuffer
b(m_name
);
1037 if (!b
.isEmpty() && b
[b
.getLength() - 1] == '/') {
1038 if (path
[0] == '/') {
1039 b
.append(path
.copy(1));
1044 if (path
[0] != '/') {
1049 return b
.makeStringAndClear();
1052 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */