tdf#131098 docx export: write fill property of graphic
[LibreOffice.git] / registry / source / keyimpl.cxx
blob34e51483e7ccc3cb2d77cd1f469c4517ce911e24
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>
32 #include <utility>
34 using namespace store;
36 namespace { char const VALUE_PREFIX[] = "$VL_"; }
38 ORegKey::ORegKey(OUString keyName, ORegistry* pReg)
39 : m_refCount(1)
40 , m_name(std::move(keyName))
41 , m_bDeleted(false)
42 , m_bModified(false)
43 , m_pRegistry(pReg)
47 ORegKey::~ORegKey()
49 SAL_WARN_IF(m_refCount != 0, "registry", "registry::ORegKey::dtor(): refcount not zero.");
52 RegError ORegKey::releaseKey(RegKeyHandle hKey)
54 return m_pRegistry->releaseKey(hKey);
57 RegError ORegKey::createKey(std::u16string_view keyName, RegKeyHandle* phNewKey)
59 return m_pRegistry->createKey(this, keyName, phNewKey);
62 RegError ORegKey::openKey(std::u16string_view keyName, RegKeyHandle* phOpenKey)
64 return m_pRegistry->openKey(this, keyName, phOpenKey);
67 RegError ORegKey::openSubKeys(std::u16string_view keyName, RegKeyHandle** phOpenSubKeys, sal_uInt32* pnSubKeys)
69 RegError _ret = RegError::NO_ERROR;
71 *phOpenSubKeys = nullptr;
72 *pnSubKeys = 0;
74 ORegKey* pKey = this;
75 if ( !keyName.empty() )
77 _ret = openKey(keyName, reinterpret_cast<RegKeyHandle*>(&pKey));
78 if (_ret != RegError::NO_ERROR)
79 return _ret;
82 sal_uInt32 nSubKeys = pKey->countSubKeys();
83 *pnSubKeys = nSubKeys;
85 ORegKey** pSubKeys;
86 pSubKeys = static_cast<ORegKey**>(rtl_allocateZeroMemory(nSubKeys * sizeof(ORegKey*)));
88 OStoreDirectory::iterator iter;
89 OStoreDirectory rStoreDir(pKey->getStoreDir());
90 storeError _err = rStoreDir.first(iter);
92 nSubKeys = 0;
93 while ( _err == store_E_None )
95 if ( iter.m_nAttrib & STORE_ATTRIB_ISDIR )
97 OUString const sSubKeyName(iter.m_pszName, iter.m_nLength);
99 ORegKey* pOpenSubKey = nullptr;
100 _ret = pKey->openKey(sSubKeyName, reinterpret_cast<RegKeyHandle*>(&pOpenSubKey));
101 if (_ret != RegError::NO_ERROR)
103 *phOpenSubKeys = nullptr;
104 *pnSubKeys = 0;
105 std::free(pSubKeys); // @@@ leaking 'pSubKeys[0...nSubkeys-1]'
106 return _ret; // @@@ leaking 'pKey'
109 pSubKeys[nSubKeys] = pOpenSubKey;
111 nSubKeys++;
114 _err = rStoreDir.next(iter);
117 *phOpenSubKeys = reinterpret_cast<RegKeyHandle*>(pSubKeys);
118 if (!keyName.empty())
120 (void) releaseKey(pKey);
122 return RegError::NO_ERROR;
125 RegError ORegKey::getKeyNames(std::u16string_view keyName,
126 rtl_uString*** pSubKeyNames,
127 sal_uInt32* pnSubKeys)
129 *pSubKeyNames = nullptr;
130 *pnSubKeys = 0;
132 ORegKey* pKey = this;
133 if (!keyName.empty())
135 RegError _ret = openKey(keyName, reinterpret_cast<RegKeyHandle*>(&pKey));
136 if (_ret != RegError::NO_ERROR)
137 return _ret;
140 sal_uInt32 nSubKeys = pKey->countSubKeys();
141 *pnSubKeys = nSubKeys;
143 rtl_uString** pSubKeys
144 = static_cast<rtl_uString**>(rtl_allocateZeroMemory(nSubKeys * sizeof(rtl_uString*)));
146 OStoreDirectory::iterator iter;
147 OStoreDirectory rStoreDir(pKey->getStoreDir());
148 storeError _err = rStoreDir.first(iter);
150 nSubKeys = 0;
152 while ( _err == store_E_None )
154 if ( iter.m_nAttrib & STORE_ATTRIB_ISDIR)
156 OUString const sSubKeyName(iter.m_pszName, iter.m_nLength);
158 OUString sFullKeyName(pKey->getName());
159 if (sFullKeyName.getLength() > 1)
160 sFullKeyName += ORegistry::ROOT;
161 sFullKeyName += sSubKeyName;
163 rtl_uString_newFromString(&pSubKeys[nSubKeys], sFullKeyName.pData);
165 nSubKeys++;
168 _err = rStoreDir.next(iter);
171 *pSubKeyNames = pSubKeys;
172 if (!keyName.empty())
174 releaseKey(pKey);
176 return RegError::NO_ERROR;
179 RegError ORegKey::closeKey(RegKeyHandle hKey)
181 return m_pRegistry->closeKey(hKey);
184 RegError ORegKey::deleteKey(std::u16string_view keyName)
186 return m_pRegistry->deleteKey(this, keyName);
189 RegError ORegKey::getValueInfo(std::u16string_view valueName, RegValueType* pValueType, sal_uInt32* pValueSize) const
191 OStoreStream rValue;
192 std::unique_ptr<sal_uInt8[]> pBuffer;
193 storeAccessMode accessMode = storeAccessMode::ReadWrite;
195 if (m_pRegistry->isReadOnly())
197 accessMode = storeAccessMode::ReadOnly;
200 OUString sImplValueName = OUString::Concat(VALUE_PREFIX) + valueName;
202 REG_GUARD(m_pRegistry->m_mutex);
204 if ( rValue.create(m_pRegistry->getStoreFile(), m_name + ORegistry::ROOT, sImplValueName, accessMode) )
206 *pValueType = RegValueType::NOT_DEFINED;
207 *pValueSize = 0;
208 return RegError::VALUE_NOT_EXISTS;
211 pBuffer.reset(new sal_uInt8[VALUE_HEADERSIZE]);
213 sal_uInt32 readBytes;
214 if ( rValue.readAt(0, pBuffer.get(), VALUE_HEADERSIZE, readBytes) )
216 return RegError::INVALID_VALUE;
218 if (readBytes != VALUE_HEADERSIZE)
220 return RegError::INVALID_VALUE;
223 sal_uInt32 size;
224 sal_uInt8 type = pBuffer[0];
225 readUINT32(pBuffer.get()+VALUE_TYPEOFFSET, size);
227 *pValueType = static_cast<RegValueType>(type);
228 if (*pValueType > RegValueType::BINARY)
230 pBuffer.reset(new sal_uInt8[4]);
231 rValue.readAt(VALUE_HEADEROFFSET, pBuffer.get(), 4, readBytes);
233 readUINT32(pBuffer.get(), size);
236 *pValueSize = size;
238 return RegError::NO_ERROR;
241 RegError ORegKey::setValue(std::u16string_view valueName, RegValueType vType, RegValue value, sal_uInt32 vSize)
243 OStoreStream rValue;
244 std::unique_ptr<sal_uInt8[]> pBuffer;
246 if (m_pRegistry->isReadOnly())
248 return RegError::REGISTRY_READONLY;
251 if (vType > RegValueType::BINARY)
253 return RegError::INVALID_VALUE;
256 OUString sImplValueName = OUString::Concat(VALUE_PREFIX) + valueName;
258 REG_GUARD(m_pRegistry->m_mutex);
260 if ( rValue.create(getStoreFile(), m_name + ORegistry::ROOT , sImplValueName, storeAccessMode::Create) )
262 return RegError::SET_VALUE_FAILED;
265 sal_uInt32 size = vSize;
267 sal_uInt8 type = static_cast<sal_uInt8>(vType);
268 pBuffer.reset(new sal_uInt8[VALUE_HEADERSIZE + size]);
269 memcpy(pBuffer.get(), &type, 1);
271 writeUINT32(pBuffer.get()+VALUE_TYPEOFFSET, size);
273 switch (vType)
275 case RegValueType::NOT_DEFINED:
276 memcpy(pBuffer.get()+VALUE_HEADEROFFSET, value, size);
277 break;
278 case RegValueType::LONG:
279 writeINT32(pBuffer.get()+VALUE_HEADEROFFSET, *static_cast<sal_Int32*>(value));
280 break;
281 case RegValueType::STRING:
282 writeUtf8(pBuffer.get()+VALUE_HEADEROFFSET, static_cast<const char*>(value));
283 break;
284 case RegValueType::UNICODE:
285 writeString(pBuffer.get()+VALUE_HEADEROFFSET, static_cast<const sal_Unicode*>(value));
286 break;
287 case RegValueType::BINARY:
288 memcpy(pBuffer.get()+VALUE_HEADEROFFSET, value, size);
289 break;
290 default:
291 OSL_ASSERT(false);
292 break;
295 sal_uInt32 writenBytes;
296 if ( rValue.writeAt(0, pBuffer.get(), VALUE_HEADERSIZE+size, writenBytes) )
298 return RegError::SET_VALUE_FAILED;
300 if (writenBytes != (VALUE_HEADERSIZE+size))
302 return RegError::SET_VALUE_FAILED;
304 setModified();
306 return RegError::NO_ERROR;
309 RegError ORegKey::setLongListValue(std::u16string_view valueName, sal_Int32 const * pValueList, sal_uInt32 len)
311 OStoreStream rValue;
312 std::unique_ptr<sal_uInt8[]> pBuffer;
314 if (m_pRegistry->isReadOnly())
316 return RegError::REGISTRY_READONLY;
319 OUString sImplValueName = OUString::Concat(VALUE_PREFIX) + valueName;
321 REG_GUARD(m_pRegistry->m_mutex);
323 if (rValue.create(getStoreFile(), m_name + ORegistry::ROOT, sImplValueName, storeAccessMode::Create) )
325 return RegError::SET_VALUE_FAILED;
328 sal_uInt32 size = 4; // 4 bytes (sal_uInt32) for the length
330 size += len * 4;
332 sal_uInt8 type = sal_uInt8(RegValueType::LONGLIST);
333 pBuffer.reset(new sal_uInt8[VALUE_HEADERSIZE + size]);
334 memcpy(pBuffer.get(), &type, 1);
336 writeUINT32(pBuffer.get()+VALUE_TYPEOFFSET, size);
337 writeUINT32(pBuffer.get()+VALUE_HEADEROFFSET, len);
339 sal_uInt32 offset = 4; // initial 4 bytes for the size of the array
341 for (sal_uInt32 i=0; i < len; i++)
343 writeINT32(pBuffer.get()+VALUE_HEADEROFFSET+offset, pValueList[i]);
344 offset += 4;
347 sal_uInt32 writenBytes;
348 if ( rValue.writeAt(0, pBuffer.get(), VALUE_HEADERSIZE+size, writenBytes) )
350 return RegError::SET_VALUE_FAILED;
352 if (writenBytes != (VALUE_HEADEROFFSET+size))
354 return RegError::SET_VALUE_FAILED;
356 setModified();
358 return RegError::NO_ERROR;
361 RegError ORegKey::setStringListValue(
362 std::u16string_view valueName, char** pValueList, sal_uInt32 len)
364 OStoreStream rValue;
365 std::unique_ptr<sal_uInt8[]> pBuffer;
367 if (m_pRegistry->isReadOnly())
369 return RegError::REGISTRY_READONLY;
372 OUString sImplValueName = OUString::Concat(VALUE_PREFIX) + valueName;
374 REG_GUARD(m_pRegistry->m_mutex);
376 if (rValue.create(getStoreFile(), m_name + ORegistry::ROOT, sImplValueName, storeAccessMode::Create) )
378 return RegError::SET_VALUE_FAILED;
381 sal_uInt32 size = 4; // 4 bytes (sal_uInt32) for the length
383 sal_uInt32 i;
384 for (i=0; i < len; i++)
386 size += 4 + strlen(pValueList[i]) + 1;
389 sal_uInt8 type = sal_uInt8(RegValueType::STRINGLIST);
390 pBuffer.reset(new sal_uInt8[VALUE_HEADERSIZE + size]);
391 memcpy(pBuffer.get(), &type, 1);
393 writeUINT32(pBuffer.get()+VALUE_TYPEOFFSET, size);
394 writeUINT32(pBuffer.get()+VALUE_HEADEROFFSET, len);
396 sal_uInt32 offset = 4; // initial 4 bytes for the size of the array;
397 sal_uInt32 sLen = 0;
399 for (i=0; i < len; i++)
401 sLen = strlen(pValueList[i]) + 1;
402 writeUINT32(pBuffer.get()+VALUE_HEADEROFFSET+offset, sLen);
404 offset += 4;
405 writeUtf8(pBuffer.get()+VALUE_HEADEROFFSET+offset, pValueList[i]);
406 offset += sLen;
409 sal_uInt32 writenBytes;
410 if ( rValue.writeAt(0, pBuffer.get(), VALUE_HEADERSIZE+size, writenBytes) )
412 return RegError::SET_VALUE_FAILED;
414 if (writenBytes != (VALUE_HEADERSIZE+size))
416 return RegError::SET_VALUE_FAILED;
418 setModified();
420 return RegError::NO_ERROR;
423 RegError ORegKey::setUnicodeListValue(std::u16string_view valueName, sal_Unicode** pValueList, sal_uInt32 len)
425 OStoreStream rValue;
426 std::unique_ptr<sal_uInt8[]> pBuffer;
428 if (m_pRegistry->isReadOnly())
430 return RegError::REGISTRY_READONLY;
433 OUString sImplValueName = OUString::Concat(VALUE_PREFIX) + valueName;
435 REG_GUARD(m_pRegistry->m_mutex);
437 if (rValue.create(getStoreFile(), m_name + ORegistry::ROOT, sImplValueName, storeAccessMode::Create) )
439 return RegError::SET_VALUE_FAILED;
442 sal_uInt32 size = 4; // 4 bytes (sal_uInt32) for the length
444 sal_uInt32 i;
445 for (i=0; i < len; i++)
447 size += 4 + ((rtl_ustr_getLength(pValueList[i]) +1) * 2);
450 sal_uInt8 type = sal_uInt8(RegValueType::UNICODELIST);
451 pBuffer.reset(new sal_uInt8[VALUE_HEADERSIZE + size]);
452 memcpy(pBuffer.get(), &type, 1);
454 writeUINT32(pBuffer.get()+VALUE_TYPEOFFSET, size);
455 writeUINT32(pBuffer.get()+VALUE_HEADEROFFSET, len);
457 sal_uInt32 offset = 4; // initial 4 bytes for the size of the array;
458 sal_uInt32 sLen = 0;
460 for (i=0; i < len; i++)
462 sLen = (rtl_ustr_getLength(pValueList[i]) + 1) * 2;
463 writeUINT32(pBuffer.get()+VALUE_HEADEROFFSET+offset, sLen);
465 offset += 4;
466 writeString(pBuffer.get()+VALUE_HEADEROFFSET+offset, pValueList[i]);
467 offset += sLen;
470 sal_uInt32 writenBytes;
471 if ( rValue.writeAt(0, pBuffer.get(), VALUE_HEADERSIZE+size, writenBytes) )
473 return RegError::SET_VALUE_FAILED;
475 if (writenBytes != (VALUE_HEADERSIZE+size))
477 return RegError::SET_VALUE_FAILED;
479 setModified();
481 return RegError::NO_ERROR;
484 RegError ORegKey::getValue(std::u16string_view valueName, RegValue value) const
486 OStoreStream rValue;
487 std::unique_ptr<sal_uInt8[]> pBuffer;
488 RegValueType valueType;
489 sal_uInt32 valueSize;
490 storeAccessMode accessMode = storeAccessMode::ReadWrite;
492 if (m_pRegistry->isReadOnly())
494 accessMode = storeAccessMode::ReadOnly;
497 OUString sImplValueName = OUString::Concat(VALUE_PREFIX) + valueName;
499 REG_GUARD(m_pRegistry->m_mutex);
501 if (rValue.create(getStoreFile(), m_name + ORegistry::ROOT, sImplValueName, accessMode) )
503 return RegError::VALUE_NOT_EXISTS;
506 pBuffer.reset(new sal_uInt8[VALUE_HEADERSIZE]);
508 sal_uInt32 readBytes;
509 if ( rValue.readAt(0, pBuffer.get(), VALUE_HEADERSIZE, readBytes) )
511 return RegError::INVALID_VALUE;
513 if (readBytes != VALUE_HEADERSIZE)
515 return RegError::INVALID_VALUE;
518 sal_uInt8 type = pBuffer[0];
519 valueType = static_cast<RegValueType>(type);
520 readUINT32(pBuffer.get()+VALUE_TYPEOFFSET, valueSize);
522 if (valueType > RegValueType::BINARY)
524 return RegError::INVALID_VALUE;
527 pBuffer.reset(new sal_uInt8[valueSize]);
529 if ( rValue.readAt(VALUE_HEADEROFFSET, pBuffer.get(), valueSize, readBytes) )
531 return RegError::INVALID_VALUE;
533 if (readBytes != valueSize)
535 return RegError::INVALID_VALUE;
538 switch (valueType)
540 case RegValueType::LONG:
541 readINT32(pBuffer.get(), *static_cast<sal_Int32*>(value));
542 break;
543 case RegValueType::STRING:
544 readUtf8(pBuffer.get(), static_cast<char*>(value), valueSize);
545 break;
546 case RegValueType::UNICODE:
547 readString(pBuffer.get(), static_cast<sal_Unicode*>(value), valueSize);
548 break;
549 case RegValueType::BINARY:
550 memcpy(value, pBuffer.get(), valueSize);
551 break;
552 default:
553 memcpy(value, pBuffer.get(), valueSize);
554 break;
557 return RegError::NO_ERROR;
560 RegError ORegKey::getLongListValue(std::u16string_view valueName, sal_Int32** pValueList, sal_uInt32* pLen) const
562 OStoreStream rValue;
563 std::unique_ptr<sal_uInt8[]> pBuffer;
564 RegValueType valueType;
565 sal_uInt32 valueSize;
566 storeAccessMode accessMode = storeAccessMode::ReadWrite;
568 if (m_pRegistry->isReadOnly())
570 accessMode = storeAccessMode::ReadOnly;
573 OUString sImplValueName = OUString::Concat(VALUE_PREFIX) + valueName;
575 REG_GUARD(m_pRegistry->m_mutex);
577 if (rValue.create(getStoreFile(), m_name + ORegistry::ROOT, sImplValueName, accessMode) )
579 pValueList = nullptr;
580 *pLen = 0;
581 return RegError::VALUE_NOT_EXISTS;
584 pBuffer.reset(new sal_uInt8[VALUE_HEADERSIZE]);
586 sal_uInt32 readBytes;
587 if ( rValue.readAt(0, pBuffer.get(), VALUE_HEADERSIZE, readBytes) )
589 pValueList = nullptr;
590 *pLen = 0;
591 return RegError::INVALID_VALUE;
593 if (readBytes != VALUE_HEADERSIZE)
595 pValueList = nullptr;
596 *pLen = 0;
597 return RegError::INVALID_VALUE;
600 sal_uInt8 type = pBuffer[0];
601 valueType = static_cast<RegValueType>(type);
603 if (valueType != RegValueType::LONGLIST)
605 pValueList = nullptr;
606 *pLen = 0;
607 return RegError::INVALID_VALUE;
610 readUINT32(pBuffer.get()+VALUE_TYPEOFFSET, valueSize);
612 /* check for 'reasonable' value */
613 /* surely 10 millions entry in a registry list should be enough */
614 if(valueSize > 40000000)
616 pValueList = nullptr;
617 *pLen = 0;
618 return RegError::INVALID_VALUE;
620 pBuffer.reset(new sal_uInt8[valueSize]);
622 if ( rValue.readAt(VALUE_HEADEROFFSET, pBuffer.get(), valueSize, readBytes) )
624 pValueList = nullptr;
625 *pLen = 0;
626 return RegError::INVALID_VALUE;
628 if (readBytes != valueSize)
630 pValueList = nullptr;
631 *pLen = 0;
632 return RegError::INVALID_VALUE;
635 sal_uInt32 len = 0;
636 readUINT32(pBuffer.get(), len);
638 /* make sure the declared size of the array is consistent with the amount of data we have read */
639 if(len > (valueSize - 4) / 4)
641 pValueList = nullptr;
642 *pLen = 0;
643 return RegError::INVALID_VALUE;
645 *pLen = len;
646 sal_Int32* pVList = static_cast<sal_Int32*>(rtl_allocateZeroMemory(len * sizeof(sal_Int32)));
648 sal_uInt32 offset = 4; // initial 4 bytes for the size of the array;
650 for (sal_uInt32 i = 0; i < len; i++)
652 readINT32(pBuffer.get()+offset, pVList[i]);
653 offset += 4;
656 *pValueList = pVList;
657 return RegError::NO_ERROR;
660 RegError ORegKey::getStringListValue(std::u16string_view valueName, char*** pValueList, sal_uInt32* pLen) const
662 OStoreStream rValue;
663 std::unique_ptr<sal_uInt8[]> pBuffer;
664 RegValueType valueType;
665 sal_uInt32 valueSize;
666 storeAccessMode accessMode = storeAccessMode::ReadWrite;
668 if (m_pRegistry->isReadOnly())
670 accessMode = storeAccessMode::ReadOnly;
673 OUString sImplValueName = OUString::Concat(VALUE_PREFIX) + valueName;
675 REG_GUARD(m_pRegistry->m_mutex);
677 if ( rValue.create(getStoreFile(), m_name + ORegistry::ROOT, sImplValueName, accessMode) )
679 pValueList = nullptr;
680 *pLen = 0;
681 return RegError::VALUE_NOT_EXISTS;
684 pBuffer.reset(new sal_uInt8[VALUE_HEADERSIZE]);
686 sal_uInt32 readBytes;
687 if ( rValue.readAt(0, pBuffer.get(), VALUE_HEADERSIZE, readBytes) )
689 pValueList = nullptr;
690 *pLen = 0;
691 return RegError::INVALID_VALUE;
693 if (readBytes != VALUE_HEADERSIZE)
695 pValueList = nullptr;
696 *pLen = 0;
697 return RegError::INVALID_VALUE;
700 sal_uInt8 type = pBuffer[0];
701 valueType = static_cast<RegValueType>(type);
703 if (valueType != RegValueType::STRINGLIST)
705 pValueList = nullptr;
706 *pLen = 0;
707 return RegError::INVALID_VALUE;
710 readUINT32(pBuffer.get()+VALUE_TYPEOFFSET, valueSize);
712 pBuffer.reset(new sal_uInt8[valueSize]);
714 if ( rValue.readAt(VALUE_HEADEROFFSET, pBuffer.get(), valueSize, readBytes) )
716 pValueList = nullptr;
717 *pLen = 0;
718 return RegError::INVALID_VALUE;
720 if (readBytes != valueSize)
722 pValueList = nullptr;
723 *pLen = 0;
724 return RegError::INVALID_VALUE;
727 sal_uInt32 len = 0;
728 readUINT32(pBuffer.get(), len);
730 *pLen = len;
731 char** pVList = static_cast<char**>(rtl_allocateZeroMemory(len * sizeof(char*)));
733 sal_uInt32 offset = 4; // initial 4 bytes for the size of the array;
734 sal_uInt32 sLen = 0;
736 char *pValue;
737 for (sal_uInt32 i=0; i < len; i++)
739 readUINT32(pBuffer.get()+offset, sLen);
741 offset += 4;
743 pValue = static_cast<char*>(std::malloc(sLen));
744 readUtf8(pBuffer.get()+offset, pValue, sLen);
745 pVList[i] = pValue;
747 offset += sLen;
750 *pValueList = pVList;
751 return RegError::NO_ERROR;
754 RegError ORegKey::getUnicodeListValue(std::u16string_view valueName, sal_Unicode*** pValueList, sal_uInt32* pLen) const
756 OStoreStream rValue;
757 std::unique_ptr<sal_uInt8[]> pBuffer;
758 RegValueType valueType;
759 sal_uInt32 valueSize;
760 storeAccessMode accessMode = storeAccessMode::ReadWrite;
762 if (m_pRegistry->isReadOnly())
764 accessMode = storeAccessMode::ReadOnly;
767 OUString sImplValueName = OUString::Concat(VALUE_PREFIX) + valueName;
769 REG_GUARD(m_pRegistry->m_mutex);
771 if ( rValue.create(getStoreFile(), m_name + ORegistry::ROOT, sImplValueName, accessMode) )
773 pValueList = nullptr;
774 *pLen = 0;
775 return RegError::VALUE_NOT_EXISTS;
778 pBuffer.reset(new sal_uInt8[VALUE_HEADERSIZE]);
780 sal_uInt32 readBytes;
781 if ( rValue.readAt(0, pBuffer.get(), VALUE_HEADERSIZE, readBytes) )
783 pValueList = nullptr;
784 *pLen = 0;
785 return RegError::INVALID_VALUE;
787 if (readBytes != VALUE_HEADERSIZE)
789 pValueList = nullptr;
790 *pLen = 0;
791 return RegError::INVALID_VALUE;
794 sal_uInt8 type = pBuffer[0];
795 valueType = static_cast<RegValueType>(type);
797 if (valueType != RegValueType::UNICODELIST)
799 pValueList = nullptr;
800 *pLen = 0;
801 return RegError::INVALID_VALUE;
804 readUINT32(pBuffer.get()+VALUE_TYPEOFFSET, valueSize);
806 pBuffer.reset(new sal_uInt8[valueSize]);
808 if ( rValue.readAt(VALUE_HEADEROFFSET, pBuffer.get(), valueSize, readBytes) )
810 pValueList = nullptr;
811 *pLen = 0;
812 return RegError::INVALID_VALUE;
814 if (readBytes != valueSize)
816 pValueList = nullptr;
817 *pLen = 0;
818 return RegError::INVALID_VALUE;
821 sal_uInt32 len = 0;
822 readUINT32(pBuffer.get(), len);
824 *pLen = len;
825 sal_Unicode** pVList = static_cast<sal_Unicode**>(rtl_allocateZeroMemory(len * sizeof(sal_Unicode*)));
827 sal_uInt32 offset = 4; // initial 4 bytes for the size of the array;
828 sal_uInt32 sLen = 0;
830 sal_Unicode *pValue;
831 for (sal_uInt32 i=0; i < len; i++)
833 readUINT32(pBuffer.get()+offset, sLen);
835 offset += 4;
837 pValue = static_cast<sal_Unicode*>(std::malloc((sLen / 2) * sizeof(sal_Unicode)));
838 readString(pBuffer.get()+offset, pValue, sLen);
839 pVList[i] = pValue;
841 offset += sLen;
844 *pValueList = pVList;
845 return RegError::NO_ERROR;
849 RegError ORegKey::getResolvedKeyName(std::u16string_view keyName,
850 OUString& resolvedName) const
852 if (keyName.empty())
853 return RegError::INVALID_KEYNAME;
855 resolvedName = getFullPath(keyName);
856 return RegError::NO_ERROR;
859 sal_uInt32 ORegKey::countSubKeys()
861 REG_GUARD(m_pRegistry->m_mutex);
863 OStoreDirectory::iterator iter;
864 OStoreDirectory rStoreDir = getStoreDir();
865 storeError _err = rStoreDir.first(iter);
866 sal_uInt32 count = 0;
868 while ( _err == store_E_None )
870 if ( iter.m_nAttrib & STORE_ATTRIB_ISDIR )
872 count++;
875 _err = rStoreDir.next(iter);
878 return count;
881 OStoreDirectory ORegKey::getStoreDir() const
883 OStoreDirectory rStoreDir;
884 OUString fullPath;
885 OUString relativName;
886 storeAccessMode accessMode = storeAccessMode::ReadWrite;
888 if ( m_name == ORegistry::ROOT )
890 fullPath.clear();
891 relativName.clear();
892 } else
894 fullPath = m_name.copy(0, m_name.lastIndexOf('/') + 1);
895 relativName = m_name.copy(m_name.lastIndexOf('/') + 1);
898 if (m_pRegistry->isReadOnly())
900 accessMode = storeAccessMode::ReadOnly;
903 rStoreDir.create(getStoreFile(), fullPath, relativName, accessMode);
905 return rStoreDir;
908 OUString ORegKey::getFullPath(std::u16string_view path) const {
909 OSL_ASSERT(!m_name.isEmpty() && !path.empty());
910 OUStringBuffer b(32);
911 b.append(m_name);
912 if (!b.isEmpty() && b[b.getLength() - 1] == '/') {
913 if (path[0] == '/') {
914 b.append(path.substr(1));
915 } else {
916 b.append(path);
918 } else {
919 if (path[0] != '/') {
920 b.append('/');
922 b.append(path);
924 return b.makeStringAndClear();
927 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */