Fix typo
[LibreOffice.git] / registry / source / regimpl.cxx
blob7dcbaa272dab321f2699f157ff4588452d77eb0b
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 "regimpl.hxx"
23 #include <cstddef>
24 #include <memory>
25 #include <set>
26 #include <string_view>
27 #include <vector>
28 #include <string.h>
29 #include <stdio.h>
31 #if defined(UNX)
32 #include <unistd.h>
33 #endif
35 #include <registry/reader.hxx>
36 #include <registry/refltype.hxx>
37 #include <registry/types.hxx>
39 #include "reflcnst.hxx"
40 #include "keyimpl.hxx"
42 #include <osl/thread.h>
43 #include <rtl/ustring.hxx>
44 #include <rtl/ustrbuf.hxx>
45 #include <osl/file.hxx>
47 using namespace osl;
48 using namespace store;
51 namespace {
53 void printString(std::u16string_view s) {
54 printf("\"");
55 for (std::size_t i = 0; i < s.size(); ++i) {
56 sal_Unicode c = s[i];
57 if (c == '"' || c == '\\') {
58 printf("\\%c", static_cast< char >(c));
59 } else if (s[i] >= ' ' && s[i] <= '~') {
60 printf("%c", static_cast< char >(c));
61 } else {
62 printf("\\u%04X", static_cast< unsigned int >(c));
65 printf("\"");
68 void printFieldOrReferenceFlag(
69 RTFieldAccess * flags, RTFieldAccess flag, char const * name, bool * first)
71 if ((*flags & flag) != RTFieldAccess::NONE) {
72 if (!*first) {
73 printf("|");
75 *first = false;
76 printf("%s", name);
77 *flags &= ~flag;
81 void printFieldOrReferenceFlags(RTFieldAccess flags) {
82 if (flags == RTFieldAccess::NONE) {
83 printf("none");
84 } else {
85 bool first = true;
86 printFieldOrReferenceFlag(
87 &flags, RTFieldAccess::READONLY, "readonly", &first);
88 printFieldOrReferenceFlag(
89 &flags, RTFieldAccess::OPTIONAL, "optional", &first);
90 printFieldOrReferenceFlag(
91 &flags, RTFieldAccess::MAYBEVOID, "maybevoid", &first);
92 printFieldOrReferenceFlag(&flags, RTFieldAccess::BOUND, "bound", &first);
93 printFieldOrReferenceFlag(
94 &flags, RTFieldAccess::CONSTRAINED, "constrained", &first);
95 printFieldOrReferenceFlag(
96 &flags, RTFieldAccess::TRANSIENT, "transient", &first);
97 printFieldOrReferenceFlag(
98 &flags, RTFieldAccess::MAYBEAMBIGUOUS, "maybeambiguous", &first);
99 printFieldOrReferenceFlag(
100 &flags, RTFieldAccess::MAYBEDEFAULT, "maybedefault", &first);
101 printFieldOrReferenceFlag(
102 &flags, RTFieldAccess::REMOVABLE, "removable", &first);
103 printFieldOrReferenceFlag(
104 &flags, RTFieldAccess::ATTRIBUTE, "attribute", &first);
105 printFieldOrReferenceFlag(
106 &flags, RTFieldAccess::PROPERTY, "property", &first);
107 printFieldOrReferenceFlag(&flags, RTFieldAccess::CONST, "const", &first);
108 printFieldOrReferenceFlag(
109 &flags, RTFieldAccess::READWRITE, "readwrite", &first);
110 printFieldOrReferenceFlag(
111 &flags, RTFieldAccess::PARAMETERIZED_TYPE, "parameterized type", &first);
112 printFieldOrReferenceFlag(
113 &flags, RTFieldAccess::PUBLISHED, "published", &first);
114 if (flags != RTFieldAccess::NONE) {
115 if (!first) {
116 printf("|");
118 printf("<invalid (0x%04X)>", static_cast< unsigned int >(flags));
123 void dumpType(typereg::Reader const & reader, OString const & indent) {
124 if (reader.isValid()) {
125 printf("version: %ld\n", static_cast< long >(reader.getVersion()));
126 printf("%sdocumentation: ", indent.getStr());
127 printString(reader.getDocumentation());
128 printf("\n");
129 printf("%sfile name: ", indent.getStr());
130 printString(reader.getFileName());
131 printf("\n");
132 printf("%stype class: ", indent.getStr());
133 if (reader.isPublished()) {
134 printf("published ");
136 switch (reader.getTypeClass()) {
137 case RT_TYPE_INTERFACE:
138 printf("interface");
139 break;
141 case RT_TYPE_MODULE:
142 printf("module");
143 break;
145 case RT_TYPE_STRUCT:
146 printf("struct");
147 break;
149 case RT_TYPE_ENUM:
150 printf("enum");
151 break;
153 case RT_TYPE_EXCEPTION:
154 printf("exception");
155 break;
157 case RT_TYPE_TYPEDEF:
158 printf("typedef");
159 break;
161 case RT_TYPE_SERVICE:
162 printf("service");
163 break;
165 case RT_TYPE_SINGLETON:
166 printf("singleton");
167 break;
169 case RT_TYPE_CONSTANTS:
170 printf("constants");
171 break;
173 default:
174 printf(
175 "<invalid (%ld)>", static_cast< long >(reader.getTypeClass()));
176 break;
178 printf("\n");
179 printf("%stype name: ", indent.getStr());
180 printString(reader.getTypeName());
181 printf("\n");
182 printf(
183 "%ssuper type count: %u\n", indent.getStr(),
184 static_cast< unsigned int >(reader.getSuperTypeCount()));
185 for (sal_uInt16 i = 0; i < reader.getSuperTypeCount(); ++i) {
186 printf(
187 "%ssuper type name %u: ", indent.getStr(),
188 static_cast< unsigned int >(i));
189 printString(reader.getSuperTypeName(i));
190 printf("\n");
192 printf(
193 "%sfield count: %u\n", indent.getStr(),
194 static_cast< unsigned int >(reader.getFieldCount()));
195 for (sal_uInt16 i = 0; i < reader.getFieldCount(); ++i) {
196 printf(
197 "%sfield %u:\n", indent.getStr(),
198 static_cast< unsigned int >(i));
199 printf("%s documentation: ", indent.getStr());
200 printString(reader.getFieldDocumentation(i));
201 printf("\n");
202 printf("%s file name: ", indent.getStr());
203 printString(reader.getFieldFileName(i));
204 printf("\n");
205 printf("%s flags: ", indent.getStr());
206 printFieldOrReferenceFlags(reader.getFieldFlags(i));
207 printf("\n");
208 printf("%s name: ", indent.getStr());
209 printString(reader.getFieldName(i));
210 printf("\n");
211 printf("%s type name: ", indent.getStr());
212 printString(reader.getFieldTypeName(i));
213 printf("\n");
214 printf("%s value: ", indent.getStr());
215 RTConstValue value(reader.getFieldValue(i));
216 switch (value.m_type) {
217 case RT_TYPE_NONE:
218 printf("none");
219 break;
221 case RT_TYPE_BOOL:
222 printf("boolean %s", value.m_value.aBool ? "true" : "false");
223 break;
225 case RT_TYPE_BYTE:
226 printf("byte %d", static_cast< int >(value.m_value.aByte));
227 break;
229 case RT_TYPE_INT16:
230 printf("short %d", static_cast< int >(value.m_value.aShort));
231 break;
233 case RT_TYPE_UINT16:
234 printf(
235 "unsigned short %u",
236 static_cast< unsigned int >(value.m_value.aUShort));
237 break;
239 case RT_TYPE_INT32:
240 printf("long %ld", static_cast< long >(value.m_value.aLong));
241 break;
243 case RT_TYPE_UINT32:
244 printf(
245 "unsigned long %lu",
246 static_cast< unsigned long >(value.m_value.aULong));
247 break;
249 case RT_TYPE_INT64:
250 // TODO: no portable way to print hyper values
251 printf("hyper");
252 break;
254 case RT_TYPE_UINT64:
255 // TODO: no portable way to print unsigned hyper values
256 printf("unsigned hyper");
257 break;
259 case RT_TYPE_FLOAT:
260 // TODO: no portable way to print float values
261 printf("float");
262 break;
264 case RT_TYPE_DOUBLE:
265 // TODO: no portable way to print double values
266 printf("double");
267 break;
269 case RT_TYPE_STRING:
270 printf("string ");
271 printString(value.m_value.aString);
272 break;
274 default:
275 printf("<invalid (%ld)>", static_cast< long >(value.m_type));
276 break;
278 printf("\n");
280 printf(
281 "%smethod count: %u\n", indent.getStr(),
282 static_cast< unsigned int >(reader.getMethodCount()));
283 for (sal_uInt16 i = 0; i < reader.getMethodCount(); ++i) {
284 printf(
285 "%smethod %u:\n", indent.getStr(),
286 static_cast< unsigned int >(i));
287 printf("%s documentation: ", indent.getStr());
288 printString(reader.getMethodDocumentation(i));
289 printf("\n");
290 printf("%s flags: ", indent.getStr());
291 switch (reader.getMethodFlags(i)) {
292 case RTMethodMode::ONEWAY:
293 printf("oneway");
294 break;
296 case RTMethodMode::TWOWAY:
297 printf("synchronous");
298 break;
300 case RTMethodMode::ATTRIBUTE_GET:
301 printf("attribute get");
302 break;
304 case RTMethodMode::ATTRIBUTE_SET:
305 printf("attribute set");
306 break;
308 default:
309 printf(
310 "<invalid (%ld)>",
311 static_cast< long >(reader.getMethodFlags(i)));
312 break;
314 printf("\n");
315 printf("%s name: ", indent.getStr());
316 printString(reader.getMethodName(i));
317 printf("\n");
318 printf("%s return type name: ", indent.getStr());
319 printString(reader.getMethodReturnTypeName(i));
320 printf("\n");
321 printf(
322 "%s parameter count: %u\n", indent.getStr(),
323 static_cast< unsigned int >(reader.getMethodParameterCount(i)));
324 // coverity[tainted_data] - cid#1215304 unhelpfully warns about untrusted loop bound
325 for (sal_uInt16 j = 0; j < reader.getMethodParameterCount(i); ++j)
327 printf(
328 "%s parameter %u:\n", indent.getStr(),
329 static_cast< unsigned int >(j));
330 printf("%s flags: ", indent.getStr());
331 RTParamMode flags = reader.getMethodParameterFlags(i, j);
332 bool rest = (flags & RT_PARAM_REST) != 0;
333 switch (flags & ~RT_PARAM_REST) {
334 case RT_PARAM_IN:
335 printf("in");
336 break;
338 case RT_PARAM_OUT:
339 printf("out");
340 break;
342 case RT_PARAM_INOUT:
343 printf("inout");
344 break;
346 default:
347 printf("<invalid (%ld)>", static_cast< long >(flags));
348 rest = false;
349 break;
351 if (rest) {
352 printf("|rest");
354 printf("\n");
355 printf("%s name: ", indent.getStr());
356 printString(reader.getMethodParameterName(i, j));
357 printf("\n");
358 printf("%s type name: ", indent.getStr());
359 printString(reader.getMethodParameterTypeName(i, j));
360 printf("\n");
362 printf(
363 "%s exception count: %u\n", indent.getStr(),
364 static_cast< unsigned int >(reader.getMethodExceptionCount(i)));
365 // coverity[tainted_data] - cid#1215304 unhelpfully warns about untrusted loop bound
366 for (sal_uInt16 j = 0; j < reader.getMethodExceptionCount(i); ++j)
368 printf(
369 "%s exception type name %u: ", indent.getStr(),
370 static_cast< unsigned int >(j));
371 printString(reader.getMethodExceptionTypeName(i, j));
372 printf("\n");
375 printf(
376 "%sreference count: %u\n", indent.getStr(),
377 static_cast< unsigned int >(reader.getReferenceCount()));
378 for (sal_uInt16 i = 0; i < reader.getReferenceCount(); ++i) {
379 printf(
380 "%sreference %u:\n", indent.getStr(),
381 static_cast< unsigned int >(i));
382 printf("%s documentation: ", indent.getStr());
383 printString(reader.getReferenceDocumentation(i));
384 printf("\n");
385 printf("%s flags: ", indent.getStr());
386 printFieldOrReferenceFlags(reader.getReferenceFlags(i));
387 printf("\n");
388 printf("%s sort: ", indent.getStr());
389 switch (reader.getReferenceSort(i)) {
390 case RTReferenceType::SUPPORTS:
391 printf("supports");
392 break;
394 case RTReferenceType::EXPORTS:
395 printf("exports");
396 break;
398 case RTReferenceType::TYPE_PARAMETER:
399 printf("type parameter");
400 break;
402 default:
403 printf(
404 "<invalid (%ld)>",
405 static_cast< long >(reader.getReferenceSort(i)));
406 break;
408 printf("\n");
409 printf("%s type name: ", indent.getStr());
410 printString(reader.getReferenceTypeName(i));
411 printf("\n");
413 } else {
414 printf("<invalid>\n");
420 ORegistry::ORegistry()
421 : m_refCount(1)
422 , m_readOnly(false)
423 , m_isOpen(false)
427 ORegistry::~ORegistry()
429 ORegKey* pRootKey = m_openKeyTable[ROOT];
430 if (pRootKey != nullptr)
431 (void) releaseKey(pRootKey);
433 if (m_file.isValid())
434 m_file.close();
437 RegError ORegistry::initRegistry(const OUString& regName, RegAccessMode accessMode, bool bCreate)
439 RegError eRet = RegError::INVALID_REGISTRY;
440 OStoreFile rRegFile;
441 storeAccessMode sAccessMode = storeAccessMode::ReadWrite;
442 storeError errCode;
444 if (bCreate)
446 sAccessMode = storeAccessMode::Create;
448 else if (accessMode & RegAccessMode::READONLY)
450 sAccessMode = storeAccessMode::ReadOnly;
451 m_readOnly = true;
454 if (regName.isEmpty() &&
455 storeAccessMode::Create == sAccessMode)
457 errCode = rRegFile.createInMemory();
459 else
461 errCode = rRegFile.create(regName, sAccessMode);
464 if (errCode)
466 switch (errCode)
468 case store_E_NotExists:
469 eRet = RegError::REGISTRY_NOT_EXISTS;
470 break;
471 case store_E_LockingViolation:
472 eRet = RegError::CANNOT_OPEN_FOR_READWRITE;
473 break;
474 default:
475 eRet = RegError::INVALID_REGISTRY;
476 break;
479 else
481 OStoreDirectory rStoreDir;
482 storeError _err = rStoreDir.create(rRegFile, OUString(), OUString(), sAccessMode);
484 if (_err == store_E_None)
486 m_file = rRegFile;
487 m_name = regName;
488 m_isOpen = true;
490 m_openKeyTable[ROOT] = new ORegKey(ROOT, this);
491 eRet = RegError::NO_ERROR;
493 else
494 eRet = RegError::INVALID_REGISTRY;
497 return eRet;
500 RegError ORegistry::closeRegistry()
502 REG_GUARD(m_mutex);
504 if (m_file.isValid())
506 (void) releaseKey(m_openKeyTable[ROOT]);
507 m_file.close();
508 m_isOpen = false;
509 return RegError::NO_ERROR;
510 } else
512 return RegError::REGISTRY_NOT_EXISTS;
516 RegError ORegistry::destroyRegistry(const OUString& regName)
518 REG_GUARD(m_mutex);
520 if (!regName.isEmpty())
522 std::unique_ptr<ORegistry> pReg(new ORegistry());
524 if (pReg->initRegistry(regName, RegAccessMode::READWRITE) == RegError::NO_ERROR)
526 pReg.reset();
528 OUString systemName;
529 if (FileBase::getSystemPathFromFileURL(regName, systemName) != FileBase::E_None)
530 systemName = regName;
532 OString name(OUStringToOString(systemName, osl_getThreadTextEncoding()));
533 if (unlink(name.getStr()) != 0)
535 return RegError::DESTROY_REGISTRY_FAILED;
537 } else
539 return RegError::DESTROY_REGISTRY_FAILED;
541 } else
543 if (m_refCount != 1 || isReadOnly())
545 return RegError::DESTROY_REGISTRY_FAILED;
548 if (m_file.isValid())
550 releaseKey(m_openKeyTable[ROOT]);
551 m_file.close();
552 m_isOpen = false;
554 if (!m_name.isEmpty())
556 OUString systemName;
557 if (FileBase::getSystemPathFromFileURL(m_name, systemName) != FileBase::E_None)
558 systemName = m_name;
560 OString name(OUStringToOString(systemName, osl_getThreadTextEncoding()));
561 if (unlink(name.getStr()) != 0)
563 return RegError::DESTROY_REGISTRY_FAILED;
566 } else
568 return RegError::REGISTRY_NOT_EXISTS;
572 return RegError::NO_ERROR;
575 RegError ORegistry::acquireKey (RegKeyHandle hKey)
577 ORegKey* pKey = static_cast< ORegKey* >(hKey);
578 if (!pKey)
579 return RegError::INVALID_KEY;
581 REG_GUARD(m_mutex);
582 pKey->acquire();
584 return RegError::NO_ERROR;
587 RegError ORegistry::releaseKey (RegKeyHandle hKey)
589 ORegKey* pKey = static_cast< ORegKey* >(hKey);
590 if (!pKey)
591 return RegError::INVALID_KEY;
593 REG_GUARD(m_mutex);
594 if (pKey->release() == 0)
596 m_openKeyTable.erase(pKey->getName());
597 delete pKey;
599 return RegError::NO_ERROR;
602 RegError ORegistry::createKey(RegKeyHandle hKey, std::u16string_view keyName,
603 RegKeyHandle* phNewKey)
605 ORegKey* pKey;
607 *phNewKey = nullptr;
609 if (keyName.empty())
610 return RegError::INVALID_KEYNAME;
612 REG_GUARD(m_mutex);
614 if (hKey)
615 pKey = static_cast<ORegKey*>(hKey);
616 else
617 pKey = m_openKeyTable[ROOT];
619 OUString sFullKeyName = pKey->getFullPath(keyName);
621 if (m_openKeyTable.count(sFullKeyName) > 0)
623 *phNewKey = m_openKeyTable[sFullKeyName];
624 static_cast<ORegKey*>(*phNewKey)->acquire();
625 static_cast<ORegKey*>(*phNewKey)->setDeleted(false);
626 return RegError::NO_ERROR;
629 OStoreDirectory rStoreDir;
630 OUStringBuffer sFullPath(sFullKeyName.getLength()+16);
631 OUString token;
633 sFullPath.append('/');
635 sal_Int32 nIndex = 0;
638 token = sFullKeyName.getToken(0, '/', nIndex);
639 if (!token.isEmpty())
641 if (rStoreDir.create(pKey->getStoreFile(), sFullPath.toString(), token, storeAccessMode::Create))
643 return RegError::CREATE_KEY_FAILED;
646 sFullPath.append(token + "/");
648 } while(nIndex != -1);
651 pKey = new ORegKey(sFullKeyName, this);
652 *phNewKey = pKey;
653 m_openKeyTable[sFullKeyName] = pKey;
655 return RegError::NO_ERROR;
658 RegError ORegistry::openKey(RegKeyHandle hKey, std::u16string_view keyName,
659 RegKeyHandle* phOpenKey)
661 ORegKey* pKey;
663 *phOpenKey = nullptr;
665 if (keyName.empty())
667 return RegError::INVALID_KEYNAME;
670 REG_GUARD(m_mutex);
672 if (hKey)
673 pKey = static_cast<ORegKey*>(hKey);
674 else
675 pKey = m_openKeyTable[ROOT];
677 OUString path(pKey->getFullPath(keyName));
678 KeyMap::iterator i(m_openKeyTable.find(path));
679 if (i == m_openKeyTable.end()) {
680 sal_Int32 n = path.lastIndexOf('/') + 1;
681 switch (OStoreDirectory().create(
682 pKey->getStoreFile(), path.copy(0, n), path.copy(n),
683 isReadOnly() ? storeAccessMode::ReadOnly : storeAccessMode::ReadWrite))
685 case store_E_NotExists:
686 return RegError::KEY_NOT_EXISTS;
687 case store_E_WrongFormat:
688 return RegError::INVALID_KEY;
689 default:
690 break;
693 std::unique_ptr< ORegKey > p(new ORegKey(path, this));
694 i = m_openKeyTable.insert(std::make_pair(path, p.get())).first;
695 // coverity[leaked_storage : FALSE] - ownership transferred to m_openKeyTable
696 p.release();
697 } else {
698 i->second->acquire();
700 *phOpenKey = i->second;
701 return RegError::NO_ERROR;
704 RegError ORegistry::closeKey(RegKeyHandle hKey)
706 ORegKey* pKey = static_cast< ORegKey* >(hKey);
708 REG_GUARD(m_mutex);
710 OUString const aKeyName (pKey->getName());
711 if (m_openKeyTable.count(aKeyName) <= 0)
712 return RegError::KEY_NOT_OPEN;
714 if (pKey->isModified())
716 ORegKey * pRootKey = getRootKey();
717 if (pKey != pRootKey)
719 // propagate "modified" state to RootKey.
720 pRootKey->setModified();
722 else
724 // closing modified RootKey, flush registry file.
725 (void) m_file.flush();
727 pKey->setModified(false);
728 (void) releaseKey(pRootKey);
731 return releaseKey(pKey);
734 RegError ORegistry::deleteKey(RegKeyHandle hKey, std::u16string_view keyName)
736 ORegKey* pKey = static_cast< ORegKey* >(hKey);
737 if (keyName.empty())
738 return RegError::INVALID_KEYNAME;
740 REG_GUARD(m_mutex);
742 if (!pKey)
743 pKey = m_openKeyTable[ROOT];
745 OUString sFullKeyName(pKey->getFullPath(keyName));
746 return eraseKey(m_openKeyTable[ROOT], sFullKeyName);
749 RegError ORegistry::eraseKey(ORegKey* pKey, std::u16string_view keyName)
751 RegError _ret = RegError::NO_ERROR;
753 if (keyName.empty())
755 return RegError::INVALID_KEYNAME;
758 OUString sFullKeyName(pKey->getName());
759 OUString sFullPath(sFullKeyName);
760 OUString sRelativKey;
761 size_t lastIndex = keyName.rfind('/');
763 if (lastIndex != std::u16string_view::npos)
765 sRelativKey += keyName.substr(lastIndex + 1);
767 if (sFullKeyName.getLength() > 1)
768 sFullKeyName += keyName;
769 else
770 sFullKeyName += keyName.substr(1);
772 sFullPath = sFullKeyName.copy(0, keyName.rfind('/') + 1);
773 } else
775 if (sFullKeyName.getLength() > 1)
776 sFullKeyName += ROOT;
778 sRelativKey += keyName;
779 sFullKeyName += keyName;
781 if (sFullPath.getLength() > 1)
782 sFullPath += ROOT;
785 ORegKey* pOldKey = nullptr;
786 _ret = pKey->openKey(keyName, reinterpret_cast<RegKeyHandle*>(&pOldKey));
787 if (_ret != RegError::NO_ERROR)
788 return _ret;
790 _ret = deleteSubkeysAndValues(pOldKey);
791 if (_ret != RegError::NO_ERROR)
793 pKey->closeKey(pOldKey);
794 return _ret;
797 OUString tmpName = sRelativKey + ROOT;
799 OStoreFile sFile(pKey->getStoreFile());
800 if (sFile.isValid() && sFile.remove(sFullPath, tmpName))
802 return RegError::DELETE_KEY_FAILED;
804 pOldKey->setModified();
806 // set flag deleted !!!
807 pOldKey->setDeleted(true);
809 return pKey->closeKey(pOldKey);
812 RegError ORegistry::deleteSubkeysAndValues(ORegKey* pKey)
814 OStoreDirectory::iterator iter;
815 RegError _ret = RegError::NO_ERROR;
816 OStoreDirectory rStoreDir(pKey->getStoreDir());
817 storeError _err = rStoreDir.first(iter);
819 while (_err == store_E_None)
821 OUString const keyName(iter.m_pszName, iter.m_nLength);
823 if (iter.m_nAttrib & STORE_ATTRIB_ISDIR)
825 _ret = eraseKey(pKey, keyName);
826 if (_ret != RegError::NO_ERROR)
827 return _ret;
829 else
831 OUString sFullPath(pKey->getName());
833 if (sFullPath.getLength() > 1)
834 sFullPath += ROOT;
836 if (const_cast<OStoreFile&>(pKey->getStoreFile()).remove(sFullPath, keyName))
838 return RegError::DELETE_VALUE_FAILED;
840 pKey->setModified();
843 _err = rStoreDir.next(iter);
846 return RegError::NO_ERROR;
849 ORegKey* ORegistry::getRootKey()
851 m_openKeyTable[ROOT]->acquire();
852 return m_openKeyTable[ROOT];
855 RegError ORegistry::dumpRegistry(RegKeyHandle hKey) const
857 ORegKey *pKey = static_cast<ORegKey*>(hKey);
858 OUString sName;
859 RegError _ret = RegError::NO_ERROR;
860 OStoreDirectory::iterator iter;
861 OStoreDirectory rStoreDir(pKey->getStoreDir());
862 storeError _err = rStoreDir.first(iter);
864 OString regName(OUStringToOString(getName(), osl_getThreadTextEncoding()));
865 OString keyName(OUStringToOString(pKey->getName(), RTL_TEXTENCODING_UTF8));
866 fprintf(stdout, "Registry \"%s\":\n\n%s\n", regName.getStr(), keyName.getStr());
868 while (_err == store_E_None)
870 sName = OUString(iter.m_pszName, iter.m_nLength);
872 if (iter.m_nAttrib & STORE_ATTRIB_ISDIR)
874 _ret = dumpKey(pKey->getName(), sName, 1);
875 } else
877 _ret = dumpValue(pKey->getName(), sName, 1);
880 if (_ret != RegError::NO_ERROR)
882 return _ret;
885 _err = rStoreDir.next(iter);
888 return RegError::NO_ERROR;
891 RegError ORegistry::dumpValue(const OUString& sPath, const OUString& sName, sal_Int16 nSpc) const
893 OStoreStream rValue;
894 sal_uInt32 valueSize;
895 RegValueType valueType;
896 OUString sFullPath(sPath);
897 OString sIndent;
898 storeAccessMode accessMode = storeAccessMode::ReadWrite;
900 if (isReadOnly())
902 accessMode = storeAccessMode::ReadOnly;
905 for (int i= 0; i < nSpc; i++) sIndent += " ";
907 if (sFullPath.getLength() > 1)
909 sFullPath += ROOT;
911 if (rValue.create(m_file, sFullPath, sName, accessMode))
913 return RegError::VALUE_NOT_EXISTS;
916 std::vector<sal_uInt8> aBuffer(VALUE_HEADERSIZE);
918 sal_uInt32 rwBytes;
919 if (rValue.readAt(0, aBuffer.data(), VALUE_HEADERSIZE, rwBytes))
921 return RegError::INVALID_VALUE;
923 if (rwBytes != (VALUE_HEADERSIZE))
925 return RegError::INVALID_VALUE;
928 sal_uInt8 type = aBuffer[0];
929 valueType = static_cast<RegValueType>(type);
930 readUINT32(aBuffer.data() + VALUE_TYPEOFFSET, valueSize);
932 aBuffer.resize(valueSize);
933 if (rValue.readAt(VALUE_HEADEROFFSET, aBuffer.data(), valueSize, rwBytes))
935 return RegError::INVALID_VALUE;
937 if (rwBytes != valueSize)
939 return RegError::INVALID_VALUE;
942 const char* indent = sIndent.getStr();
943 switch (valueType)
945 case RegValueType::NOT_DEFINED:
946 fprintf(stdout, "%sValue: Type = VALUETYPE_NOT_DEFINED\n", indent);
947 break;
948 case RegValueType::LONG:
950 fprintf(stdout, "%sValue: Type = RegValueType::LONG\n", indent);
951 fprintf(
952 stdout, "%s Size = %lu\n", indent,
953 sal::static_int_cast< unsigned long >(valueSize));
954 fprintf(stdout, "%s Data = ", indent);
956 sal_Int32 value;
957 readINT32(aBuffer.data(), value);
958 fprintf(stdout, "%ld\n", sal::static_int_cast< long >(value));
960 break;
961 case RegValueType::STRING:
963 char* value = static_cast<char*>(std::malloc(valueSize));
964 readUtf8(aBuffer.data(), value, valueSize);
965 fprintf(stdout, "%sValue: Type = RegValueType::STRING\n", indent);
966 fprintf(
967 stdout, "%s Size = %lu\n", indent,
968 sal::static_int_cast< unsigned long >(valueSize));
969 fprintf(stdout, "%s Data = \"%s\"\n", indent, value);
970 std::free(value);
972 break;
973 case RegValueType::UNICODE:
975 sal_uInt32 size = (valueSize / 2) * sizeof(sal_Unicode);
976 fprintf(stdout, "%sValue: Type = RegValueType::UNICODE\n", indent);
977 fprintf(
978 stdout, "%s Size = %lu\n", indent,
979 sal::static_int_cast< unsigned long >(valueSize));
980 fprintf(stdout, "%s Data = ", indent);
982 std::unique_ptr<sal_Unicode[]> value(new sal_Unicode[size]);
983 readString(aBuffer.data(), value.get(), size);
985 OString uStr(value.get(), rtl_ustr_getLength(value.get()), RTL_TEXTENCODING_UTF8);
986 fprintf(stdout, "L\"%s\"\n", uStr.getStr());
988 break;
989 case RegValueType::BINARY:
991 fprintf(stdout, "%sValue: Type = RegValueType::BINARY\n", indent);
992 fprintf(
993 stdout, "%s Size = %lu\n", indent,
994 sal::static_int_cast< unsigned long >(valueSize));
995 fprintf(stdout, "%s Data = ", indent);
996 dumpType(
997 typereg::Reader(aBuffer.data(), valueSize),
998 sIndent + " ");
1000 break;
1001 case RegValueType::LONGLIST:
1003 sal_uInt32 offset = 4; // initial 4 bytes for the size of the array
1004 sal_uInt32 len = 0;
1006 readUINT32(aBuffer.data(), len);
1008 fprintf(stdout, "%sValue: Type = RegValueType::LONGLIST\n", indent);
1009 fprintf(
1010 stdout, "%s Size = %lu\n", indent,
1011 sal::static_int_cast< unsigned long >(valueSize));
1012 fprintf(
1013 stdout, "%s Len = %lu\n", indent,
1014 sal::static_int_cast< unsigned long >(len));
1015 fprintf(stdout, "%s Data = ", indent);
1017 sal_Int32 longValue;
1018 for (sal_uInt32 i=0; i < len; i++)
1020 readINT32(aBuffer.data() + offset, longValue);
1022 if (offset > 4)
1023 fprintf(stdout, "%s ", indent);
1025 fprintf(
1026 stdout, "%lu = %ld\n",
1027 sal::static_int_cast< unsigned long >(i),
1028 sal::static_int_cast< long >(longValue));
1029 offset += 4; // 4 Bytes for sal_Int32
1032 break;
1033 case RegValueType::STRINGLIST:
1035 sal_uInt32 offset = 4; // initial 4 bytes for the size of the array
1036 sal_uInt32 sLen = 0;
1037 sal_uInt32 len = 0;
1039 readUINT32(aBuffer.data(), len);
1041 fprintf(stdout, "%sValue: Type = RegValueType::STRINGLIST\n", indent);
1042 fprintf(
1043 stdout, "%s Size = %lu\n", indent,
1044 sal::static_int_cast< unsigned long >(valueSize));
1045 fprintf(
1046 stdout, "%s Len = %lu\n", indent,
1047 sal::static_int_cast< unsigned long >(len));
1048 fprintf(stdout, "%s Data = ", indent);
1050 for (sal_uInt32 i=0; i < len; i++)
1052 readUINT32(aBuffer.data() + offset, sLen);
1054 offset += 4; // 4 bytes (sal_uInt32) for the string size
1056 char *pValue = static_cast<char*>(std::malloc(sLen));
1057 readUtf8(aBuffer.data() + offset, pValue, sLen);
1059 if (offset > 8)
1060 fprintf(stdout, "%s ", indent);
1062 fprintf(
1063 stdout, "%lu = \"%s\"\n",
1064 sal::static_int_cast< unsigned long >(i), pValue);
1065 std::free(pValue);
1066 offset += sLen;
1069 break;
1070 case RegValueType::UNICODELIST:
1072 sal_uInt32 offset = 4; // initial 4 bytes for the size of the array
1073 sal_uInt32 sLen = 0;
1074 sal_uInt32 len = 0;
1076 readUINT32(aBuffer.data(), len);
1078 fprintf(stdout, "%sValue: Type = RegValueType::UNICODELIST\n", indent);
1079 fprintf(
1080 stdout, "%s Size = %lu\n", indent,
1081 sal::static_int_cast< unsigned long >(valueSize));
1082 fprintf(
1083 stdout, "%s Len = %lu\n", indent,
1084 sal::static_int_cast< unsigned long >(len));
1085 fprintf(stdout, "%s Data = ", indent);
1087 OString uStr;
1088 for (sal_uInt32 i=0; i < len; i++)
1090 readUINT32(aBuffer.data() + offset, sLen);
1092 offset += 4; // 4 bytes (sal_uInt32) for the string size
1094 sal_Unicode *pValue = static_cast<sal_Unicode*>(std::malloc((sLen / 2) * sizeof(sal_Unicode)));
1095 readString(aBuffer.data() + offset, pValue, sLen);
1097 if (offset > 8)
1098 fprintf(stdout, "%s ", indent);
1100 uStr = OString(pValue, rtl_ustr_getLength(pValue), RTL_TEXTENCODING_UTF8);
1101 fprintf(
1102 stdout, "%lu = L\"%s\"\n",
1103 sal::static_int_cast< unsigned long >(i),
1104 uStr.getStr());
1106 offset += sLen;
1108 std::free(pValue);
1111 break;
1114 fprintf(stdout, "\n");
1116 return RegError::NO_ERROR;
1119 RegError ORegistry::dumpKey(const OUString& sPath, const OUString& sName, sal_Int16 nSpace) const
1121 OStoreDirectory rStoreDir;
1122 OUString sFullPath(sPath);
1123 OString sIndent;
1124 storeAccessMode accessMode = storeAccessMode::ReadWrite;
1125 RegError _ret = RegError::NO_ERROR;
1127 if (isReadOnly())
1129 accessMode = storeAccessMode::ReadOnly;
1132 for (int i= 0; i < nSpace; i++) sIndent += " ";
1134 if (sFullPath.getLength() > 1)
1135 sFullPath += ROOT;
1137 storeError _err = rStoreDir.create(m_file, sFullPath, sName, accessMode);
1139 if (_err == store_E_NotExists)
1140 return RegError::KEY_NOT_EXISTS;
1141 else if (_err == store_E_WrongFormat)
1142 return RegError::INVALID_KEY;
1144 fprintf(stdout, "%s/ %s\n", sIndent.getStr(), OUStringToOString(sName, RTL_TEXTENCODING_UTF8).getStr());
1146 OUString sSubPath(sFullPath);
1147 OUString sSubName;
1148 sSubPath += sName;
1150 OStoreDirectory::iterator iter;
1152 _err = rStoreDir.first(iter);
1154 while (_err == store_E_None)
1156 sSubName = OUString(iter.m_pszName, iter.m_nLength);
1158 if (iter.m_nAttrib & STORE_ATTRIB_ISDIR)
1160 _ret = dumpKey(sSubPath, sSubName, nSpace+2);
1161 } else
1163 _ret = dumpValue(sSubPath, sSubName, nSpace+2);
1166 if (_ret != RegError::NO_ERROR)
1168 return _ret;
1171 _err = rStoreDir.next(iter);
1174 return RegError::NO_ERROR;
1177 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */