nss: upgrade to release 3.73
[LibreOffice.git] / registry / source / keyimpl.cxx
blob437aa3114e10ca34e8780e80f8f9d6c3a57f2c01
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 <string.h>
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>
31 #include <memory>
33 using namespace store;
35 namespace { char const VALUE_PREFIX[] = "$VL_"; }
38 // ORegKey()
40 ORegKey::ORegKey(const OUString& keyName, ORegistry* pReg)
41 : m_refCount(1)
42 , m_name(keyName)
43 , m_bDeleted(false)
44 , m_bModified(false)
45 , m_pRegistry(pReg)
50 // ~ORegKey()
52 ORegKey::~ORegKey()
54 SAL_WARN_IF(m_refCount != 0, "registry", "registry::ORegKey::dtor(): refcount not zero.");
58 // releaseKey
60 RegError ORegKey::releaseKey(RegKeyHandle hKey)
62 return m_pRegistry->releaseKey(hKey);
66 // createKey
68 RegError ORegKey::createKey(const OUString& keyName, RegKeyHandle* phNewKey)
70 return m_pRegistry->createKey(this, keyName, phNewKey);
74 // openKey
76 RegError ORegKey::openKey(const OUString& keyName, RegKeyHandle* phOpenKey)
78 return m_pRegistry->openKey(this, keyName, phOpenKey);
82 // openSubKeys
84 RegError ORegKey::openSubKeys(const OUString& keyName, RegKeyHandle** phOpenSubKeys, sal_uInt32* pnSubKeys)
86 RegError _ret = RegError::NO_ERROR;
88 *phOpenSubKeys = nullptr;
89 *pnSubKeys = 0;
91 ORegKey* pKey = this;
92 if ( !keyName.isEmpty() )
94 _ret = openKey(keyName, reinterpret_cast<RegKeyHandle*>(&pKey));
95 if (_ret != RegError::NO_ERROR)
96 return _ret;
99 sal_uInt32 nSubKeys = pKey->countSubKeys();
100 *pnSubKeys = nSubKeys;
102 ORegKey** pSubKeys;
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);
109 nSubKeys = 0;
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;
121 *pnSubKeys = 0;
122 std::free(pSubKeys); // @@@ leaking 'pSubKeys[0...nSubkeys-1]'
123 return _ret; // @@@ leaking 'pKey'
126 pSubKeys[nSubKeys] = pOpenSubKey;
128 nSubKeys++;
131 _err = rStoreDir.next(iter);
134 *phOpenSubKeys = reinterpret_cast<RegKeyHandle*>(pSubKeys);
135 if (!keyName.isEmpty())
137 (void) releaseKey(pKey);
139 return RegError::NO_ERROR;
143 // getKeyNames
145 RegError ORegKey::getKeyNames(const OUString& keyName,
146 rtl_uString*** pSubKeyNames,
147 sal_uInt32* pnSubKeys)
149 *pSubKeyNames = nullptr;
150 *pnSubKeys = 0;
152 ORegKey* pKey = this;
153 if (!keyName.isEmpty())
155 RegError _ret = openKey(keyName, reinterpret_cast<RegKeyHandle*>(&pKey));
156 if (_ret != RegError::NO_ERROR)
157 return _ret;
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);
170 nSubKeys = 0;
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);
185 nSubKeys++;
188 _err = rStoreDir.next(iter);
191 *pSubKeyNames = pSubKeys;
192 if (!keyName.isEmpty())
194 releaseKey(pKey);
196 return RegError::NO_ERROR;
200 // closeKey
202 RegError ORegKey::closeKey(RegKeyHandle hKey)
204 return m_pRegistry->closeKey(hKey);
208 // deleteKey
210 RegError ORegKey::deleteKey(const OUString& keyName)
212 return m_pRegistry->deleteKey(this, keyName);
216 // getValueType
218 RegError ORegKey::getValueInfo(const OUString& valueName, RegValueType* pValueType, sal_uInt32* pValueSize) const
220 OStoreStream rValue;
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;
236 *pValueSize = 0;
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;
252 sal_uInt32 size;
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);
265 *pValueSize = size;
267 return RegError::NO_ERROR;
271 // setValue
273 RegError ORegKey::setValue(const OUString& valueName, RegValueType vType, RegValue value, sal_uInt32 vSize)
275 OStoreStream rValue;
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);
305 switch (vType)
307 case RegValueType::NOT_DEFINED:
308 memcpy(pBuffer.get()+VALUE_HEADEROFFSET, value, size);
309 break;
310 case RegValueType::LONG:
311 writeINT32(pBuffer.get()+VALUE_HEADEROFFSET, *static_cast<sal_Int32*>(value));
312 break;
313 case RegValueType::STRING:
314 writeUtf8(pBuffer.get()+VALUE_HEADEROFFSET, static_cast<const char*>(value));
315 break;
316 case RegValueType::UNICODE:
317 writeString(pBuffer.get()+VALUE_HEADEROFFSET, static_cast<const sal_Unicode*>(value));
318 break;
319 case RegValueType::BINARY:
320 memcpy(pBuffer.get()+VALUE_HEADEROFFSET, value, size);
321 break;
322 default:
323 OSL_ASSERT(false);
324 break;
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;
336 setModified();
338 return RegError::NO_ERROR;
342 // setLongListValue
344 RegError ORegKey::setLongListValue(const OUString& valueName, sal_Int32 const * pValueList, sal_uInt32 len)
346 OStoreStream rValue;
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
365 size += len * 4;
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]);
379 offset += 4;
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;
391 setModified();
393 return RegError::NO_ERROR;
397 // setStringListValue
399 RegError ORegKey::setStringListValue(const OUString& valueName, char** pValueList, sal_uInt32 len)
401 OStoreStream rValue;
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
420 sal_uInt32 i;
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;
434 sal_uInt32 sLen = 0;
436 for (i=0; i < len; i++)
438 sLen = strlen(pValueList[i]) + 1;
439 writeUINT32(pBuffer.get()+VALUE_HEADEROFFSET+offset, sLen);
441 offset += 4;
442 writeUtf8(pBuffer.get()+VALUE_HEADEROFFSET+offset, pValueList[i]);
443 offset += sLen;
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;
455 setModified();
457 return RegError::NO_ERROR;
461 // setUnicodeListValue
463 RegError ORegKey::setUnicodeListValue(const OUString& valueName, sal_Unicode** pValueList, sal_uInt32 len)
465 OStoreStream rValue;
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
484 sal_uInt32 i;
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;
498 sal_uInt32 sLen = 0;
500 for (i=0; i < len; i++)
502 sLen = (rtl_ustr_getLength(pValueList[i]) + 1) * 2;
503 writeUINT32(pBuffer.get()+VALUE_HEADEROFFSET+offset, sLen);
505 offset += 4;
506 writeString(pBuffer.get()+VALUE_HEADEROFFSET+offset, pValueList[i]);
507 offset += sLen;
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;
519 setModified();
521 return RegError::NO_ERROR;
525 // getValue
527 RegError ORegKey::getValue(const OUString& valueName, RegValue value) const
529 OStoreStream rValue;
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;
581 switch (valueType)
583 case RegValueType::NOT_DEFINED:
584 memcpy(value, pBuffer.get(), valueSize);
585 break;
586 case RegValueType::LONG:
587 readINT32(pBuffer.get(), *static_cast<sal_Int32*>(value));
588 break;
589 case RegValueType::STRING:
590 readUtf8(pBuffer.get(), static_cast<char*>(value), valueSize);
591 break;
592 case RegValueType::UNICODE:
593 readString(pBuffer.get(), static_cast<sal_Unicode*>(value), valueSize);
594 break;
595 case RegValueType::BINARY:
596 memcpy(value, pBuffer.get(), valueSize);
597 break;
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);
603 break;
606 return RegError::NO_ERROR;
610 // getLongListValue
612 RegError ORegKey::getLongListValue(const OUString& valueName, sal_Int32** pValueList, sal_uInt32* pLen) const
614 OStoreStream rValue;
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;
632 *pLen = 0;
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;
642 *pLen = 0;
643 return RegError::INVALID_VALUE;
645 if (readBytes != VALUE_HEADERSIZE)
647 pValueList = nullptr;
648 *pLen = 0;
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;
658 *pLen = 0;
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;
669 *pLen = 0;
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;
677 *pLen = 0;
678 return RegError::INVALID_VALUE;
680 if (readBytes != valueSize)
682 pValueList = nullptr;
683 *pLen = 0;
684 return RegError::INVALID_VALUE;
687 sal_uInt32 len = 0;
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;
694 *pLen = 0;
695 return RegError::INVALID_VALUE;
697 *pLen = len;
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]);
705 offset += 4;
708 *pValueList = pVList;
709 return RegError::NO_ERROR;
713 // getStringListValue
715 RegError ORegKey::getStringListValue(const OUString& valueName, char*** pValueList, sal_uInt32* pLen) const
717 OStoreStream rValue;
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;
735 *pLen = 0;
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;
745 *pLen = 0;
746 return RegError::INVALID_VALUE;
748 if (readBytes != VALUE_HEADERSIZE)
750 pValueList = nullptr;
751 *pLen = 0;
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;
761 *pLen = 0;
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;
772 *pLen = 0;
773 return RegError::INVALID_VALUE;
775 if (readBytes != valueSize)
777 pValueList = nullptr;
778 *pLen = 0;
779 return RegError::INVALID_VALUE;
782 sal_uInt32 len = 0;
783 readUINT32(pBuffer.get(), len);
785 *pLen = 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;
789 sal_uInt32 sLen = 0;
791 char *pValue;
792 for (sal_uInt32 i=0; i < len; i++)
794 readUINT32(pBuffer.get()+offset, sLen);
796 offset += 4;
798 pValue = static_cast<char*>(std::malloc(sLen));
799 readUtf8(pBuffer.get()+offset, pValue, sLen);
800 pVList[i] = pValue;
802 offset += 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
814 OStoreStream rValue;
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;
832 *pLen = 0;
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;
842 *pLen = 0;
843 return RegError::INVALID_VALUE;
845 if (readBytes != VALUE_HEADERSIZE)
847 pValueList = nullptr;
848 *pLen = 0;
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;
858 *pLen = 0;
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;
869 *pLen = 0;
870 return RegError::INVALID_VALUE;
872 if (readBytes != valueSize)
874 pValueList = nullptr;
875 *pLen = 0;
876 return RegError::INVALID_VALUE;
879 sal_uInt32 len = 0;
880 readUINT32(pBuffer.get(), len);
882 *pLen = 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;
886 sal_uInt32 sLen = 0;
888 sal_Unicode *pValue;
889 for (sal_uInt32 i=0; i < len; i++)
891 readUINT32(pBuffer.get()+offset, sLen);
893 offset += 4;
895 pValue = static_cast<sal_Unicode*>(std::malloc((sLen / 2) * sizeof(sal_Unicode)));
896 readString(pBuffer.get()+offset, pValue, sLen);
897 pVList[i] = pValue;
899 offset += 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;
918 // countSubKeys()
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 )
933 count++;
936 _err = rStoreDir.next(iter);
939 return count;
942 OStoreDirectory ORegKey::getStoreDir() const
944 OStoreDirectory rStoreDir;
945 OUString fullPath;
946 OUString relativName;
947 storeAccessMode accessMode = storeAccessMode::ReadWrite;
949 if ( m_name == ORegistry::ROOT )
951 fullPath.clear();
952 relativName.clear();
953 } else
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);
966 return rStoreDir;
969 OUString ORegKey::getFullPath(OUString const & path) const {
970 OSL_ASSERT(!m_name.isEmpty() && !path.isEmpty());
971 OUStringBuffer b(32);
972 b.append(m_name);
973 if (!b.isEmpty() && b[b.getLength() - 1] == '/') {
974 if (path[0] == '/') {
975 b.append(std::u16string_view(path).substr(1));
976 } else {
977 b.append(path);
979 } else {
980 if (path[0] != '/') {
981 b.append('/');
983 b.append(path);
985 return b.makeStringAndClear();
988 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */