xref: /aoo41x/main/registry/source/regimpl.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_registry.hxx"
30 
31 #include    "regimpl.hxx"
32 
33 #include <memory>
34 #include    <string.h>
35 #include	<stdio.h>
36 
37 #if defined(UNX) || defined(OS2)
38 #include    <unistd.h>
39 #endif
40 #ifdef __MINGW32__
41 #include    <unistd.h>
42 #endif
43 
44 #ifndef __REGISTRY_REFLREAD_HXX__
45 #include    <registry/reflread.hxx>
46 #endif
47 
48 #ifndef __REGISTRY_REFLWRIT_HXX__
49 #include    <registry/reflwrit.hxx>
50 #endif
51 
52 #include "registry/reader.hxx"
53 #include "registry/refltype.hxx"
54 #include "registry/types.h"
55 #include "registry/version.h"
56 
57 #include    "reflcnst.hxx"
58 #include    "keyimpl.hxx"
59 
60 #include    <osl/thread.h>
61 #include    <rtl/alloc.h>
62 #include    <rtl/memory.h>
63 #include    <rtl/ustring.hxx>
64 #include    <rtl/ustrbuf.hxx>
65 #include    <osl/file.hxx>
66 
67 using namespace rtl;
68 using namespace osl;
69 using namespace store;
70 
71 #if defined ( GCC ) && ( defined ( SCO ) )
72 sal_helper::ORealDynamicLoader* sal_helper::ODynamicLoader<RegistryTypeReader_Api>::m_pLoader = NULL;
73 #endif
74 
75 namespace {
76 
77 void printString(rtl::OUString const & s) {
78     printf("\"");
79     for (sal_Int32 i = 0; i < s.getLength(); ++i) {
80         sal_Unicode c = s[i];
81         if (c == '"' || c == '\\') {
82             printf("\\%c", static_cast< char >(c));
83         } else if (s[i] >= ' ' && s[i] <= '~') {
84             printf("%c", static_cast< char >(c));
85         } else {
86             printf("\\u%04X", static_cast< unsigned int >(c));
87         }
88     }
89     printf("\"");
90 }
91 
92 void printFieldOrReferenceFlag(
93     RTFieldAccess * flags, RTFieldAccess flag, char const * name, bool * first)
94 {
95     if ((*flags & flag) != 0) {
96         if (!*first) {
97             printf("|");
98         }
99         *first = false;
100         printf("%s", name);
101         *flags &= ~flag;
102     }
103 }
104 
105 void printFieldOrReferenceFlags(RTFieldAccess flags) {
106     if (flags == 0) {
107         printf("none");
108     } else {
109         bool first = true;
110         printFieldOrReferenceFlag(
111             &flags, RT_ACCESS_READONLY, "readonly", &first);
112         printFieldOrReferenceFlag(
113             &flags, RT_ACCESS_OPTIONAL, "optional", &first);
114         printFieldOrReferenceFlag(
115             &flags, RT_ACCESS_MAYBEVOID, "maybevoid", &first);
116         printFieldOrReferenceFlag(&flags, RT_ACCESS_BOUND, "bound", &first);
117         printFieldOrReferenceFlag(
118             &flags, RT_ACCESS_CONSTRAINED, "constrained", &first);
119         printFieldOrReferenceFlag(
120             &flags, RT_ACCESS_TRANSIENT, "transient", &first);
121         printFieldOrReferenceFlag(
122             &flags, RT_ACCESS_MAYBEAMBIGUOUS, "maybeambiguous", &first);
123         printFieldOrReferenceFlag(
124             &flags, RT_ACCESS_MAYBEDEFAULT, "maybedefault", &first);
125         printFieldOrReferenceFlag(
126             &flags, RT_ACCESS_REMOVEABLE, "removeable", &first);
127         printFieldOrReferenceFlag(
128             &flags, RT_ACCESS_ATTRIBUTE, "attribute", &first);
129         printFieldOrReferenceFlag(
130             &flags, RT_ACCESS_PROPERTY, "property", &first);
131         printFieldOrReferenceFlag(&flags, RT_ACCESS_CONST, "const", &first);
132         printFieldOrReferenceFlag(
133             &flags, RT_ACCESS_READWRITE, "readwrite", &first);
134         printFieldOrReferenceFlag(
135             &flags, RT_ACCESS_PARAMETERIZED_TYPE, "parameterized type", &first);
136         printFieldOrReferenceFlag(
137             &flags, RT_ACCESS_PUBLISHED, "published", &first);
138         if (flags != 0) {
139             if (!first) {
140                 printf("|");
141             }
142             printf("<invalid (0x%04X)>", static_cast< unsigned int >(flags));
143         }
144     }
145 }
146 
147 void dumpType(typereg::Reader const & reader, rtl::OString const & indent) {
148     if (reader.isValid()) {
149         printf("version: %ld\n", static_cast< long >(reader.getVersion()));
150         printf("%sdocumentation: ", indent.getStr());
151         printString(reader.getDocumentation());
152         printf("\n");
153         printf("%sfile name: ", indent.getStr());
154         printString(reader.getFileName());
155         printf("\n");
156         printf("%stype class: ", indent.getStr());
157         if (reader.isPublished()) {
158             printf("published ");
159         }
160         switch (reader.getTypeClass()) {
161         case RT_TYPE_INTERFACE:
162             printf("interface");
163             break;
164 
165         case RT_TYPE_MODULE:
166             printf("module");
167             break;
168 
169         case RT_TYPE_STRUCT:
170             printf("struct");
171             break;
172 
173         case RT_TYPE_ENUM:
174             printf("enum");
175             break;
176 
177         case RT_TYPE_EXCEPTION:
178             printf("exception");
179             break;
180 
181         case RT_TYPE_TYPEDEF:
182             printf("typedef");
183             break;
184 
185         case RT_TYPE_SERVICE:
186             printf("service");
187             break;
188 
189         case RT_TYPE_SINGLETON:
190             printf("singleton");
191             break;
192 
193         case RT_TYPE_CONSTANTS:
194             printf("constants");
195             break;
196 
197         default:
198             printf(
199                 "<invalid (%ld)>", static_cast< long >(reader.getTypeClass()));
200             break;
201         }
202         printf("\n");
203         printf("%stype name: ", indent.getStr());
204         printString(reader.getTypeName());
205         printf("\n");
206         printf(
207             "%ssuper type count: %u\n", indent.getStr(),
208             static_cast< unsigned int >(reader.getSuperTypeCount()));
209         {for (sal_uInt16 i = 0; i < reader.getSuperTypeCount(); ++i) {
210             printf(
211                 "%ssuper type name %u: ", indent.getStr(),
212                 static_cast< unsigned int >(i));
213             printString(reader.getSuperTypeName(i));
214             printf("\n");
215         }}
216         printf(
217             "%sfield count: %u\n", indent.getStr(),
218             static_cast< unsigned int >(reader.getFieldCount()));
219         {for (sal_uInt16 i = 0; i < reader.getFieldCount(); ++i) {
220             printf(
221                 "%sfield %u:\n", indent.getStr(),
222                 static_cast< unsigned int >(i));
223             printf("%s    documentation: ", indent.getStr());
224             printString(reader.getFieldDocumentation(i));
225             printf("\n");
226             printf("%s    file name: ", indent.getStr());
227             printString(reader.getFieldFileName(i));
228             printf("\n");
229             printf("%s    flags: ", indent.getStr());
230             printFieldOrReferenceFlags(reader.getFieldFlags(i));
231             printf("\n");
232             printf("%s    name: ", indent.getStr());
233             printString(reader.getFieldName(i));
234             printf("\n");
235             printf("%s    type name: ", indent.getStr());
236             printString(reader.getFieldTypeName(i));
237             printf("\n");
238             printf("%s    value: ", indent.getStr());
239             RTConstValue value(reader.getFieldValue(i));
240             switch (value.m_type) {
241             case RT_TYPE_NONE:
242                 printf("none");
243                 break;
244 
245             case RT_TYPE_BOOL:
246                 printf("boolean %s", value.m_value.aBool ? "true" : "false");
247                 break;
248 
249             case RT_TYPE_BYTE:
250                 printf(
251                     "byte 0x%02X",
252                     static_cast< unsigned int >(value.m_value.aByte));
253                 break;
254 
255             case RT_TYPE_INT16:
256                 printf("short %d", static_cast< int >(value.m_value.aShort));
257                 break;
258 
259             case RT_TYPE_UINT16:
260                 printf(
261                     "unsigned short %u",
262                     static_cast< unsigned int >(value.m_value.aUShort));
263                 break;
264 
265             case RT_TYPE_INT32:
266                 printf("long %ld", static_cast< long >(value.m_value.aLong));
267                 break;
268 
269             case RT_TYPE_UINT32:
270                 printf(
271                     "unsigned long %lu",
272                     static_cast< unsigned long >(value.m_value.aULong));
273                 break;
274 
275             case RT_TYPE_INT64:
276                 // TODO: no portable way to print hyper values
277                 printf("hyper");
278                 break;
279 
280             case RT_TYPE_UINT64:
281                 // TODO: no portable way to print unsigned hyper values
282                 printf("unsigned hyper");
283                 break;
284 
285             case RT_TYPE_FLOAT:
286                 // TODO: no portable way to print float values
287                 printf("float");
288                 break;
289 
290             case RT_TYPE_DOUBLE:
291                 // TODO: no portable way to print double values
292                 printf("double");
293                 break;
294 
295             case RT_TYPE_STRING:
296                 printf("string ");
297                 printString(value.m_value.aString);
298                 break;
299 
300             default:
301                 printf("<invalid (%ld)>", static_cast< long >(value.m_type));
302                 break;
303             }
304             printf("\n");
305         }}
306         printf(
307             "%smethod count: %u\n", indent.getStr(),
308             static_cast< unsigned int >(reader.getMethodCount()));
309         {for (sal_uInt16 i = 0; i < reader.getMethodCount(); ++i) {
310             printf(
311                 "%smethod %u:\n", indent.getStr(),
312                 static_cast< unsigned int >(i));
313             printf("%s    documentation: ", indent.getStr());
314             printString(reader.getMethodDocumentation(i));
315             printf("\n");
316             printf("%s    flags: ", indent.getStr());
317             switch (reader.getMethodFlags(i)) {
318             case RT_MODE_ONEWAY:
319                 printf("oneway");
320                 break;
321 
322             case RT_MODE_TWOWAY:
323                 printf("synchronous");
324                 break;
325 
326             case RT_MODE_ATTRIBUTE_GET:
327                 printf("attribute get");
328                 break;
329 
330             case RT_MODE_ATTRIBUTE_SET:
331                 printf("attribute set");
332                 break;
333 
334             default:
335                 printf(
336                     "<invalid (%ld)>",
337                     static_cast< long >(reader.getMethodFlags(i)));
338                 break;
339             }
340             printf("\n");
341             printf("%s    name: ", indent.getStr());
342             printString(reader.getMethodName(i));
343             printf("\n");
344             printf("%s    return type name: ", indent.getStr());
345             printString(reader.getMethodReturnTypeName(i));
346             printf("\n");
347             printf(
348                 "%s    parameter count: %u\n", indent.getStr(),
349                 static_cast< unsigned int >(reader.getMethodParameterCount(i)));
350             for (sal_uInt16 j = 0; j < reader.getMethodParameterCount(i); ++j)
351             {
352                 printf(
353                     "%s    parameter %u:\n", indent.getStr(),
354                     static_cast< unsigned int >(j));
355                 printf("%s        flags: ", indent.getStr());
356                 RTParamMode flags = reader.getMethodParameterFlags(i, j);
357                 bool rest = (flags & RT_PARAM_REST) != 0;
358                 switch (flags & ~RT_PARAM_REST) {
359                 case RT_PARAM_IN:
360                     printf("in");
361                     break;
362 
363                 case RT_PARAM_OUT:
364                     printf("out");
365                     break;
366 
367                 case RT_PARAM_INOUT:
368                     printf("inout");
369                     break;
370 
371                 default:
372                     printf("<invalid (%ld)>", static_cast< long >(flags));
373                     rest = false;
374                     break;
375                 }
376                 if (rest) {
377                     printf("|rest");
378                 }
379                 printf("\n");
380                 printf("%s        name: ", indent.getStr());
381                 printString(reader.getMethodParameterName(i, j));
382                 printf("\n");
383                 printf("%s        type name: ", indent.getStr());
384                 printString(reader.getMethodParameterTypeName(i, j));
385                 printf("\n");
386             }
387             printf(
388                 "%s    exception count: %u\n", indent.getStr(),
389                 static_cast< unsigned int >(reader.getMethodExceptionCount(i)));
390             for (sal_uInt16 j = 0; j < reader.getMethodExceptionCount(i); ++j)
391             {
392                 printf(
393                     "%s    exception type name %u: ", indent.getStr(),
394                     static_cast< unsigned int >(j));
395                 printString(reader.getMethodExceptionTypeName(i, j));
396                 printf("\n");
397             }
398         }}
399         printf(
400             "%sreference count: %u\n", indent.getStr(),
401             static_cast< unsigned int >(reader.getReferenceCount()));
402         {for (sal_uInt16 i = 0; i < reader.getReferenceCount(); ++i) {
403             printf(
404                 "%sreference %u:\n", indent.getStr(),
405                 static_cast< unsigned int >(i));
406             printf("%s    documentation: ", indent.getStr());
407             printString(reader.getReferenceDocumentation(i));
408             printf("\n");
409             printf("%s    flags: ", indent.getStr());
410             printFieldOrReferenceFlags(reader.getReferenceFlags(i));
411             printf("\n");
412             printf("%s    sort: ", indent.getStr());
413             switch (reader.getReferenceSort(i)) {
414             case RT_REF_SUPPORTS:
415                 printf("supports");
416                 break;
417 
418             case RT_REF_EXPORTS:
419                 printf("exports");
420                 break;
421 
422             case RT_REF_TYPE_PARAMETER:
423                 printf("type parameter");
424                 break;
425 
426             default:
427                 printf(
428                     "<invalid (%ld)>",
429                     static_cast< long >(reader.getReferenceSort(i)));
430                 break;
431             }
432             printf("\n");
433             printf("%s    type name: ", indent.getStr());
434             printString(reader.getReferenceTypeName(i));
435             printf("\n");
436         }}
437     } else {
438         printf("<invalid>\n");
439     }
440 }
441 
442 }
443 
444 //*********************************************************************
445 //  ORegistry()
446 //
447 ORegistry::ORegistry()
448     : m_refCount(1)
449     , m_readOnly(sal_False)
450     , m_isOpen(sal_False)
451 	, ROOT( RTL_CONSTASCII_USTRINGPARAM("/") )
452 {
453 }
454 
455 //*********************************************************************
456 //  ~ORegistry()
457 //
458 ORegistry::~ORegistry()
459 {
460 	ORegKey* pRootKey = m_openKeyTable[ROOT];
461 	if (pRootKey != 0)
462 		(void) releaseKey(pRootKey);
463 
464     if (m_file.isValid())
465         m_file.close();
466 }
467 
468 
469 //*********************************************************************
470 //  initRegistry
471 //
472 RegError ORegistry::initRegistry(const OUString& regName, RegAccessMode accessMode)
473 {
474     OStoreFile      rRegFile;
475     storeAccessMode sAccessMode = REG_MODE_OPEN;
476     storeError      errCode;
477 
478     if (accessMode & REG_CREATE)
479     {
480         sAccessMode = REG_MODE_CREATE;
481     } else
482     if (accessMode & REG_READONLY)
483     {
484         sAccessMode = REG_MODE_OPENREAD;
485         m_readOnly = sal_True;
486     }
487 
488     if (0 == regName.getLength() &&
489         store_AccessCreate == sAccessMode)
490     {
491         errCode = rRegFile.createInMemory();
492     }
493     else
494     {
495         errCode = rRegFile.create(regName, sAccessMode, REG_PAGESIZE);
496     }
497 
498     if (errCode)
499     {
500         switch (errCode)
501         {
502             case  store_E_NotExists:
503                 return REG_REGISTRY_NOT_EXISTS;
504             case store_E_LockingViolation:
505                 return REG_CANNOT_OPEN_FOR_READWRITE;
506             default:
507                 return REG_INVALID_REGISTRY;
508         }
509     } else
510     {
511         OStoreDirectory rStoreDir;
512         storeError      _err = rStoreDir.create(rRegFile, OUString(), OUString(), sAccessMode);
513 
514         if ( _err == store_E_None )
515         {
516             m_file = rRegFile;
517             m_name = regName;
518             m_isOpen = sal_True;
519 
520             m_openKeyTable[ROOT] = new ORegKey(ROOT, this);
521             return REG_NO_ERROR;
522         } else
523             return REG_INVALID_REGISTRY;
524     }
525 }
526 
527 
528 //*********************************************************************
529 //  closeRegistry
530 //
531 RegError ORegistry::closeRegistry()
532 {
533     REG_GUARD(m_mutex);
534 
535     if (m_file.isValid())
536     {
537         (void) releaseKey(m_openKeyTable[ROOT]);
538         m_file.close();
539         m_isOpen = sal_False;
540         return REG_NO_ERROR;
541     } else
542     {
543         return REG_REGISTRY_NOT_EXISTS;
544     }
545 }
546 
547 
548 //*********************************************************************
549 //  destroyRegistry
550 //
551 RegError ORegistry::destroyRegistry(const OUString& regName)
552 {
553     REG_GUARD(m_mutex);
554 
555     if (regName.getLength())
556     {
557         ORegistry* pReg = new ORegistry();
558 
559         if (!pReg->initRegistry(regName, REG_READWRITE))
560         {
561             delete pReg;
562 
563 			OUString systemName;
564 			if ( FileBase::getSystemPathFromFileURL(regName, systemName) != FileBase::E_None )
565 				systemName = regName;
566 
567 			OString name( OUStringToOString(systemName, osl_getThreadTextEncoding()) );
568             if (unlink(name) != 0)
569             {
570                 return REG_DESTROY_REGISTRY_FAILED;
571             }
572         } else
573         {
574             return REG_DESTROY_REGISTRY_FAILED;
575         }
576     } else
577     {
578         if (m_refCount != 1 || isReadOnly())
579         {
580             return REG_DESTROY_REGISTRY_FAILED;
581         }
582 
583         if (m_file.isValid())
584         {
585             releaseKey(m_openKeyTable[ROOT]);
586             m_file.close();
587             m_isOpen = sal_False;
588 
589             if (m_name.getLength())
590             {
591                 OUString systemName;
592                 if ( FileBase::getSystemPathFromFileURL(m_name, systemName) != FileBase::E_None )
593                     systemName = m_name;
594 
595                 OString name( OUStringToOString(systemName, osl_getThreadTextEncoding()) );
596                 if (unlink(name.getStr()) != 0)
597                 {
598                     return REG_DESTROY_REGISTRY_FAILED;
599                 }
600             }
601         } else
602         {
603             return REG_REGISTRY_NOT_EXISTS;
604         }
605     }
606 
607     return REG_NO_ERROR;
608 }
609 
610 //*********************************************************************
611 //  acquireKey
612 //
613 RegError ORegistry::acquireKey (RegKeyHandle hKey)
614 {
615 	ORegKey* pKey = static_cast< ORegKey* >(hKey);
616 	if (!pKey)
617 		return REG_INVALID_KEY;
618 
619 	REG_GUARD(m_mutex);
620 	pKey->acquire();
621 
622 	return REG_NO_ERROR;
623 }
624 
625 //*********************************************************************
626 //  releaseKey
627 //
628 RegError ORegistry::releaseKey (RegKeyHandle hKey)
629 {
630 	ORegKey* pKey = static_cast< ORegKey* >(hKey);
631 	if (!pKey)
632 		return REG_INVALID_KEY;
633 
634 	REG_GUARD(m_mutex);
635 	if (pKey->release() == 0)
636 	{
637 		m_openKeyTable.erase(pKey->getName());
638 		delete pKey;
639 	}
640 	return REG_NO_ERROR;
641 }
642 
643 //*********************************************************************
644 //  createKey
645 //
646 RegError ORegistry::createKey(RegKeyHandle hKey, const OUString& keyName,
647                               RegKeyHandle* phNewKey)
648 {
649     ORegKey*    pKey;
650 
651     *phNewKey = NULL;
652 
653     if ( !keyName.getLength() )
654         return REG_INVALID_KEYNAME;
655 
656     REG_GUARD(m_mutex);
657 
658     if (hKey)
659         pKey = (ORegKey*)hKey;
660     else
661         pKey = m_openKeyTable[ROOT];
662 
663     OUString sFullKeyName = pKey->getFullPath(keyName);
664 
665     if (m_openKeyTable.count(sFullKeyName) > 0)
666     {
667         *phNewKey = m_openKeyTable[sFullKeyName];
668         ((ORegKey*)*phNewKey)->acquire();
669         ((ORegKey*)*phNewKey)->setDeleted(sal_False);
670         return REG_NO_ERROR;
671     }
672 
673     OStoreDirectory rStoreDir;
674     OUStringBuffer  sFullPath(sFullKeyName.getLength());
675     OUString        token;
676 
677     sFullPath.append((sal_Unicode)'/');
678 
679     sal_Int32 nIndex = 0;
680     do
681     {
682         token = sFullKeyName.getToken( 0, '/', nIndex );
683         if (token.getLength())
684         {
685             if (rStoreDir.create(pKey->getStoreFile(), sFullPath.getStr(), token, KEY_MODE_CREATE))
686             {
687                 return REG_CREATE_KEY_FAILED;
688             }
689 
690             sFullPath.append(token);
691             sFullPath.append((sal_Unicode)'/');
692         }
693     } while( nIndex != -1 );
694 
695 
696     pKey = new ORegKey(sFullKeyName, this);
697     *phNewKey = pKey;
698     m_openKeyTable[sFullKeyName] = pKey;
699 
700     return REG_NO_ERROR;
701 }
702 
703 
704 //*********************************************************************
705 //  openKey
706 //
707 RegError ORegistry::openKey(RegKeyHandle hKey, const OUString& keyName,
708                             RegKeyHandle* phOpenKey)
709 {
710     ORegKey*        pKey;
711 
712     *phOpenKey = NULL;
713 
714     if ( !keyName.getLength() )
715     {
716         return REG_INVALID_KEYNAME;
717     }
718 
719     REG_GUARD(m_mutex);
720 
721     if (hKey)
722         pKey = (ORegKey*)hKey;
723     else
724         pKey = m_openKeyTable[ROOT];
725 
726     OUString path(pKey->getFullPath(keyName));
727     KeyMap::iterator i(m_openKeyTable.find(path));
728     if (i == m_openKeyTable.end()) {
729         sal_Int32 n = path.lastIndexOf('/') + 1;
730         switch (OStoreDirectory().create(
731                     pKey->getStoreFile(), path.copy(0, n), path.copy(n),
732                     isReadOnly() ? KEY_MODE_OPENREAD : KEY_MODE_OPEN))
733         {
734         case store_E_NotExists:
735             return REG_KEY_NOT_EXISTS;
736         case store_E_WrongFormat:
737             return REG_INVALID_KEY;
738         default:
739             break;
740         }
741 
742         std::auto_ptr< ORegKey > p(new ORegKey(path, this));
743         i = m_openKeyTable.insert(std::make_pair(path, p.get())).first;
744         p.release();
745     } else {
746         i->second->acquire();
747     }
748     *phOpenKey = i->second;
749     return REG_NO_ERROR;
750 }
751 
752 
753 //*********************************************************************
754 //  closeKey
755 //
756 RegError ORegistry::closeKey(RegKeyHandle hKey)
757 {
758     ORegKey* pKey = static_cast< ORegKey* >(hKey);
759 
760     REG_GUARD(m_mutex);
761 
762 	OUString const aKeyName (pKey->getName());
763     if (!(m_openKeyTable.count(aKeyName) > 0))
764         return REG_KEY_NOT_OPEN;
765 
766 	if (pKey->isModified())
767 	{
768 		ORegKey * pRootKey = getRootKey();
769 		if (pKey != pRootKey)
770 		{
771 			// propagate "modified" state to RootKey.
772 			pRootKey->setModified();
773 		}
774 		else
775 		{
776 			// closing modified RootKey, flush registry file.
777 			OSL_TRACE("registry::ORegistry::closeKey(): flushing modified RootKey");
778 			(void) m_file.flush();
779 		}
780 		pKey->setModified(false);
781 		(void) releaseKey(pRootKey);
782 	}
783 
784 	return releaseKey(pKey);
785 }
786 
787 //*********************************************************************
788 //  deleteKey
789 //
790 RegError ORegistry::deleteKey(RegKeyHandle hKey, const OUString& keyName)
791 {
792     ORegKey* pKey = static_cast< ORegKey* >(hKey);
793     if ( !keyName.getLength() )
794         return REG_INVALID_KEYNAME;
795 
796     REG_GUARD(m_mutex);
797 
798 	if (!pKey)
799 		pKey = m_openKeyTable[ROOT];
800 
801     OUString sFullKeyName(pKey->getFullPath(keyName));
802     return eraseKey(m_openKeyTable[ROOT], sFullKeyName);
803 }
804 
805 RegError ORegistry::eraseKey(ORegKey* pKey, const OUString& keyName)
806 {
807     RegError _ret = REG_NO_ERROR;
808 
809     if ( !keyName.getLength() )
810     {
811         return REG_INVALID_KEYNAME;
812     }
813 
814     OUString     sFullKeyName(pKey->getName());
815     OUString     sFullPath(sFullKeyName);
816     OUString     sRelativKey;
817     sal_Int32	 lastIndex = keyName.lastIndexOf('/');
818 
819     if ( lastIndex >= 0 )
820     {
821         sRelativKey += keyName.copy(lastIndex + 1);
822 
823         if (sFullKeyName.getLength() > 1)
824             sFullKeyName += keyName;
825         else
826             sFullKeyName += (keyName+1);
827 
828         sFullPath = sFullKeyName.copy(0, keyName.lastIndexOf('/') + 1);
829     } else
830     {
831         if (sFullKeyName.getLength() > 1)
832             sFullKeyName += ROOT;
833 
834         sRelativKey += keyName;
835         sFullKeyName += keyName;
836 
837         if (sFullPath.getLength() > 1)
838             sFullPath += ROOT;
839     }
840 
841     ORegKey* pOldKey = 0;
842     _ret = pKey->openKey(keyName, (RegKeyHandle*)&pOldKey);
843     if (_ret != REG_NO_ERROR)
844         return _ret;
845 
846     _ret = deleteSubkeysAndValues(pOldKey);
847     if (_ret != REG_NO_ERROR)
848     {
849         pKey->closeKey(pOldKey);
850         return _ret;
851     }
852 
853     OUString tmpName(sRelativKey);
854     tmpName += ROOT;
855 
856     OStoreFile sFile(pKey->getStoreFile());
857     if ( sFile.isValid() && sFile.remove(sFullPath, tmpName) )
858     {
859         return REG_DELETE_KEY_FAILED;
860     }
861 	pOldKey->setModified();
862 
863     // set flag deleted !!!
864     pOldKey->setDeleted(sal_True);
865 
866     return pKey->closeKey(pOldKey);
867 }
868 
869 //*********************************************************************
870 //  deleteSubKeysAndValues
871 //
872 RegError ORegistry::deleteSubkeysAndValues(ORegKey* pKey)
873 {
874     OStoreDirectory::iterator   iter;
875     RegError                    _ret = REG_NO_ERROR;
876     OStoreDirectory             rStoreDir(pKey->getStoreDir());
877     storeError                  _err = rStoreDir.first(iter);
878 
879     while ( _err == store_E_None )
880     {
881         OUString const keyName = iter.m_pszName;
882 
883         if (iter.m_nAttrib & STORE_ATTRIB_ISDIR)
884         {
885             _ret = eraseKey(pKey, keyName);
886             if (_ret)
887                 return _ret;
888         }
889 		else
890         {
891             OUString sFullPath(pKey->getName());
892 
893             if (sFullPath.getLength() > 1)
894                 sFullPath += ROOT;
895 
896             if ( ((OStoreFile&)pKey->getStoreFile()).remove(sFullPath, keyName) )
897             {
898                 return REG_DELETE_VALUE_FAILED;
899             }
900 			pKey->setModified();
901         }
902 
903         _err = rStoreDir.next(iter);
904     }
905 
906     return REG_NO_ERROR;
907 }
908 
909 
910 //*********************************************************************
911 //  loadKey
912 //
913 RegError ORegistry::loadKey(RegKeyHandle hKey, const OUString& regFileName,
914                             sal_Bool bWarnings, sal_Bool bReport)
915 {
916     RegError _ret = REG_NO_ERROR;
917     ORegKey* pKey = static_cast< ORegKey* >(hKey);
918 
919     std::auto_ptr< ORegistry > pReg (new ORegistry());
920     _ret = pReg->initRegistry(regFileName, REG_READONLY);
921     if (_ret != REG_NO_ERROR)
922         return _ret;
923     ORegKey* pRootKey = pReg->getRootKey();
924 
925     REG_GUARD(m_mutex);
926 
927     OStoreDirectory::iterator   iter;
928     OStoreDirectory             rStoreDir(pRootKey->getStoreDir());
929     storeError                  _err = rStoreDir.first(iter);
930 
931     while ( _err == store_E_None )
932     {
933 		OUString const keyName = iter.m_pszName;
934 
935         if ( iter.m_nAttrib & STORE_ATTRIB_ISDIR )
936         {
937             _ret = loadAndSaveKeys(pKey, pRootKey, keyName, 0, bWarnings, bReport);
938         }
939 		else
940         {
941             _ret = loadAndSaveValue(pKey, pRootKey, keyName, 0, bWarnings, bReport);
942         }
943 
944         if (_ret == REG_MERGE_ERROR)
945 			break;
946 		if (_ret == REG_MERGE_CONFLICT && bWarnings)
947 			break;
948 
949         _err = rStoreDir.next(iter);
950     }
951 
952     rStoreDir = OStoreDirectory();
953     (void) pReg->releaseKey(pRootKey);
954     return _ret;
955 }
956 
957 
958 //*********************************************************************
959 //  saveKey
960 //
961 RegError ORegistry::saveKey(RegKeyHandle hKey, const OUString& regFileName,
962                             sal_Bool bWarnings, sal_Bool bReport)
963 {
964     RegError _ret = REG_NO_ERROR;
965     ORegKey* pKey = static_cast< ORegKey* >(hKey);
966 
967     std::auto_ptr< ORegistry > pReg (new ORegistry());
968     _ret = pReg->initRegistry(regFileName, REG_CREATE);
969     if (_ret != REG_NO_ERROR)
970         return _ret;
971     ORegKey* pRootKey = pReg->getRootKey();
972 
973     REG_GUARD(m_mutex);
974 
975     OStoreDirectory::iterator   iter;
976     OStoreDirectory             rStoreDir(pKey->getStoreDir());
977     storeError                  _err = rStoreDir.first(iter);
978 
979     while ( _err == store_E_None )
980     {
981 		OUString const keyName = iter.m_pszName;
982 
983         if ( iter.m_nAttrib & STORE_ATTRIB_ISDIR )
984         {
985             _ret = loadAndSaveKeys(pRootKey, pKey, keyName,
986                                    pKey->getName().getLength(),
987                                    bWarnings, bReport);
988         }
989 		else
990         {
991             _ret = loadAndSaveValue(pRootKey, pKey, keyName,
992                                     pKey->getName().getLength(),
993                                     bWarnings, bReport);
994         }
995 
996         if (_ret != REG_NO_ERROR)
997 			break;
998 
999         _err = rStoreDir.next(iter);
1000     }
1001 
1002     (void) pReg->releaseKey(pRootKey);
1003     return _ret;
1004 }
1005 
1006 
1007 //*********************************************************************
1008 //  loadAndSaveValue()
1009 //
1010 RegError ORegistry::loadAndSaveValue(ORegKey* pTargetKey,
1011                                      ORegKey* pSourceKey,
1012                                      const OUString& valueName,
1013                                      sal_uInt32 nCut,
1014                                      sal_Bool bWarnings,
1015                                      sal_Bool bReport)
1016 {
1017     OStoreStream    rValue;
1018     sal_uInt8*      pBuffer;
1019     RegValueType    valueType;
1020     sal_uInt32      valueSize;
1021     sal_uInt32      nSize;
1022     storeAccessMode sourceAccess = VALUE_MODE_OPEN;
1023     OUString        sTargetPath(pTargetKey->getName());
1024     OUString        sSourcePath(pSourceKey->getName());
1025 
1026     if (pSourceKey->isReadOnly())
1027     {
1028         sourceAccess = VALUE_MODE_OPENREAD;
1029     }
1030 
1031     if (nCut)
1032     {
1033         sTargetPath = sSourcePath.copy(nCut);
1034     } else
1035     {
1036         if (sTargetPath.getLength() > 1)
1037         {
1038             if (sSourcePath.getLength() > 1)
1039                 sTargetPath += sSourcePath;
1040         } else
1041             sTargetPath = sSourcePath;
1042     }
1043 
1044     if (sTargetPath.getLength() > 1) sTargetPath += ROOT;
1045     if (sSourcePath.getLength() > 1) sSourcePath += ROOT;
1046 
1047     if (rValue.create(pSourceKey->getStoreFile(), sSourcePath, valueName, sourceAccess))
1048     {
1049         return REG_VALUE_NOT_EXISTS;
1050     }
1051 
1052     pBuffer = (sal_uInt8*)rtl_allocateMemory(VALUE_HEADERSIZE);
1053 
1054     sal_uInt32  rwBytes;
1055     if (rValue.readAt(0, pBuffer, VALUE_HEADERSIZE, rwBytes))
1056     {
1057         rtl_freeMemory(pBuffer);
1058         return REG_INVALID_VALUE;
1059     }
1060     if (rwBytes != VALUE_HEADERSIZE)
1061     {
1062         rtl_freeMemory(pBuffer);
1063         return REG_INVALID_VALUE;
1064     }
1065 
1066     RegError _ret = REG_NO_ERROR;
1067     sal_uInt8   type = *((sal_uInt8*)pBuffer);
1068     valueType = (RegValueType)type;
1069     readUINT32(pBuffer+VALUE_TYPEOFFSET, valueSize);
1070     rtl_freeMemory(pBuffer);
1071 
1072     nSize = VALUE_HEADERSIZE + valueSize;
1073     pBuffer = (sal_uInt8*)rtl_allocateMemory(nSize);
1074 
1075     if (rValue.readAt(0, pBuffer, nSize, rwBytes))
1076     {
1077         rtl_freeMemory(pBuffer);
1078         return REG_INVALID_VALUE;
1079     }
1080     if (rwBytes != nSize)
1081     {
1082         rtl_freeMemory(pBuffer);
1083         return REG_INVALID_VALUE;
1084     }
1085 
1086     OStoreFile  rTargetFile(pTargetKey->getStoreFile());
1087 
1088     if (!rValue.create(rTargetFile, sTargetPath, valueName, VALUE_MODE_OPEN))
1089     {
1090         if (valueType == RG_VALUETYPE_BINARY)
1091         {
1092             _ret = checkBlop(
1093                 rValue, sTargetPath, valueSize, pBuffer+VALUE_HEADEROFFSET,
1094                 bReport);
1095             if (_ret)
1096             {
1097                 if (_ret == REG_MERGE_ERROR ||
1098                     (_ret == REG_MERGE_CONFLICT && bWarnings))
1099                 {
1100                     rtl_freeMemory(pBuffer);
1101                     return _ret;
1102                 }
1103             } else
1104             {
1105                 rtl_freeMemory(pBuffer);
1106                 return _ret;
1107             }
1108         }
1109     }
1110 
1111     // write
1112     if (rValue.create(rTargetFile, sTargetPath, valueName, VALUE_MODE_CREATE))
1113     {
1114         rtl_freeMemory(pBuffer);
1115         return REG_INVALID_VALUE;
1116     }
1117     if (rValue.writeAt(0, pBuffer, nSize, rwBytes))
1118     {
1119         rtl_freeMemory(pBuffer);
1120         return REG_INVALID_VALUE;
1121     }
1122 
1123     if (rwBytes != nSize)
1124     {
1125         rtl_freeMemory(pBuffer);
1126         return REG_INVALID_VALUE;
1127     }
1128 	pTargetKey->setModified();
1129 
1130     rtl_freeMemory(pBuffer);
1131     return _ret;
1132 }
1133 
1134 
1135 //*********************************************************************
1136 //  checkblop()
1137 //
1138 RegError ORegistry::checkBlop(OStoreStream& rValue,
1139                               const OUString& sTargetPath,
1140                               sal_uInt32 srcValueSize,
1141                               sal_uInt8* pSrcBuffer,
1142                               sal_Bool bReport)
1143 {
1144     RegistryTypeReader reader(pSrcBuffer, srcValueSize, sal_False);
1145 
1146     if (reader.getTypeClass() == RT_TYPE_INVALID)
1147     {
1148         return REG_INVALID_VALUE;
1149     }
1150 
1151     sal_uInt8*      pBuffer = (sal_uInt8*)rtl_allocateMemory(VALUE_HEADERSIZE);
1152     RegValueType    valueType;
1153     sal_uInt32      valueSize;
1154     sal_uInt32      rwBytes;
1155 	OString 		targetPath( OUStringToOString(sTargetPath, RTL_TEXTENCODING_UTF8) );
1156 
1157     if (!rValue.readAt(0, pBuffer, VALUE_HEADERSIZE, rwBytes) &&
1158         (rwBytes == VALUE_HEADERSIZE))
1159     {
1160         sal_uInt8 type = *((sal_uInt8*)pBuffer);
1161         valueType = (RegValueType)type;
1162         readUINT32(pBuffer+VALUE_TYPEOFFSET, valueSize);
1163         rtl_freeMemory(pBuffer);
1164 
1165         if (valueType == RG_VALUETYPE_BINARY)
1166         {
1167             pBuffer = (sal_uInt8*)rtl_allocateMemory(valueSize);
1168             if (!rValue.readAt(VALUE_HEADEROFFSET, pBuffer, valueSize, rwBytes) &&
1169                 (rwBytes == valueSize))
1170             {
1171                 RegistryTypeReader reader2(pBuffer, valueSize, sal_False);
1172 
1173                 if ((reader.getTypeClass() != reader2.getTypeClass())
1174                     || reader2.getTypeClass() == RT_TYPE_INVALID)
1175                 {
1176                     rtl_freeMemory(pBuffer);
1177 
1178                     if (bReport)
1179                     {
1180                         fprintf(stdout, "ERROR: values of blop from key \"%s\" has different types.\n",
1181                                 targetPath.getStr());
1182                     }
1183                     return REG_MERGE_ERROR;
1184                 }
1185 
1186                 if (reader.getTypeClass() == RT_TYPE_MODULE)
1187                 {
1188                     if (reader.getFieldCount() > 0 &&
1189                         reader2.getFieldCount() > 0)
1190                     {
1191                         mergeModuleValue(rValue, reader, reader2);
1192 
1193                         rtl_freeMemory(pBuffer);
1194                         return REG_NO_ERROR;
1195                     } else
1196                     if (reader2.getFieldCount() > 0)
1197                     {
1198                         rtl_freeMemory(pBuffer);
1199                         return REG_NO_ERROR;
1200                     } else
1201                     {
1202                         rtl_freeMemory(pBuffer);
1203                         return REG_MERGE_CONFLICT;
1204                     }
1205                 } else
1206                 {
1207                     rtl_freeMemory(pBuffer);
1208 
1209                     if (bReport)
1210                     {
1211                         fprintf(stdout, "WARNING: value of key \"%s\" already exists.\n",
1212                                 targetPath.getStr());
1213                     }
1214                     return REG_MERGE_CONFLICT;
1215                 }
1216             } else
1217             {
1218                 rtl_freeMemory(pBuffer);
1219                 if (bReport)
1220                 {
1221                     fprintf(stdout, "ERROR: values of key \"%s\" contains bad data.\n",
1222                             targetPath.getStr());
1223                 }
1224                 return REG_MERGE_ERROR;
1225             }
1226         } else
1227         {
1228             rtl_freeMemory(pBuffer);
1229             if (bReport)
1230             {
1231                 fprintf(stdout, "ERROR: values of key \"%s\" has different types.\n",
1232                         targetPath.getStr());
1233             }
1234             return REG_MERGE_ERROR;
1235         }
1236     } else
1237     {
1238         rtl_freeMemory(pBuffer);
1239         return REG_INVALID_VALUE;
1240     }
1241 }
1242 
1243 static sal_uInt32 checkTypeReaders(RegistryTypeReader& reader1,
1244                                    RegistryTypeReader& reader2,
1245                                    std::set< OUString >& nameSet)
1246 {
1247     sal_uInt32 count=0;
1248     sal_uInt16 i;
1249     for (i=0 ; i < reader1.getFieldCount(); i++)
1250     {
1251         nameSet.insert(reader1.getFieldName(i));
1252         count++;
1253     }
1254     for (i=0 ; i < reader2.getFieldCount(); i++)
1255     {
1256         if (nameSet.find(reader2.getFieldName(i)) == nameSet.end())
1257         {
1258             nameSet.insert(reader2.getFieldName(i));
1259             count++;
1260         }
1261     }
1262     return count;
1263 }
1264 
1265 //*********************************************************************
1266 //  mergeModuleValue()
1267 //
1268 RegError ORegistry::mergeModuleValue(OStoreStream& rTargetValue,
1269                                      RegistryTypeReader& reader,
1270                                      RegistryTypeReader& reader2)
1271 {
1272     sal_uInt16                  index = 0;
1273 
1274     std::set< OUString > nameSet;
1275     sal_uInt32 count = checkTypeReaders(reader, reader2, nameSet);
1276 
1277     if (count != reader.getFieldCount())
1278     {
1279         RegistryTypeWriter writer(reader.getTypeClass(),
1280                                   reader.getTypeName(),
1281                                   reader.getSuperTypeName(),
1282                                   (sal_uInt16)count,
1283                                   0,
1284                                   0);
1285 
1286         sal_uInt16 i;
1287         for (i=0 ; i < reader.getFieldCount(); i++)
1288         {
1289             writer.setFieldData(index,
1290                                reader.getFieldName(i),
1291                                reader.getFieldType(i),
1292                                reader.getFieldDoku(i),
1293                                reader.getFieldFileName(i),
1294                                reader.getFieldAccess(i),
1295                                reader.getFieldConstValue(i));
1296             index++;
1297         }
1298         for (i=0 ; i < reader2.getFieldCount(); i++)
1299         {
1300             if (nameSet.find(reader2.getFieldName(i)) == nameSet.end())
1301             {
1302                 writer.setFieldData(index,
1303                                    reader2.getFieldName(i),
1304                                    reader2.getFieldType(i),
1305                                    reader2.getFieldDoku(i),
1306                                    reader2.getFieldFileName(i),
1307                                    reader2.getFieldAccess(i),
1308                                    reader2.getFieldConstValue(i));
1309                 index++;
1310             }
1311         }
1312 
1313         const sal_uInt8*    pBlop = writer.getBlop();
1314         sal_uInt32          aBlopSize = writer.getBlopSize();
1315 
1316         sal_uInt8   type = (sal_uInt8)RG_VALUETYPE_BINARY;
1317         sal_uInt8*  pBuffer = (sal_uInt8*)rtl_allocateMemory(VALUE_HEADERSIZE + aBlopSize);
1318 
1319         rtl_copyMemory(pBuffer, &type, 1);
1320         writeUINT32(pBuffer+VALUE_TYPEOFFSET, aBlopSize);
1321         rtl_copyMemory(pBuffer+VALUE_HEADEROFFSET, pBlop, aBlopSize);
1322 
1323         sal_uInt32  rwBytes;
1324         if (rTargetValue.writeAt(0, pBuffer, VALUE_HEADERSIZE+aBlopSize, rwBytes))
1325         {
1326             rtl_freeMemory(pBuffer);
1327             return REG_INVALID_VALUE;
1328         }
1329 
1330         if (rwBytes != VALUE_HEADERSIZE+aBlopSize)
1331         {
1332             rtl_freeMemory(pBuffer);
1333             return REG_INVALID_VALUE;
1334         }
1335 
1336         rtl_freeMemory(pBuffer);
1337     }
1338     return REG_NO_ERROR;
1339 }
1340 
1341 //*********************************************************************
1342 //  loadAndSaveKeys()
1343 //
1344 RegError ORegistry::loadAndSaveKeys(ORegKey* pTargetKey,
1345                                     ORegKey* pSourceKey,
1346                                     const OUString& keyName,
1347                                     sal_uInt32 nCut,
1348                                     sal_Bool bWarnings,
1349                                     sal_Bool bReport)
1350 {
1351     RegError    _ret = REG_NO_ERROR;
1352     OUString    sRelPath(pSourceKey->getName().copy(nCut));
1353     OUString    sFullPath;
1354 
1355     if(pTargetKey->getName().getLength() > 1)
1356         sFullPath += pTargetKey->getName();
1357     sFullPath += sRelPath;
1358     if (sRelPath.getLength() > 1 || sFullPath.getLength() == 0)
1359         sFullPath += ROOT;
1360 
1361     OUString sFullKeyName = sFullPath;
1362     sFullKeyName += keyName;
1363 
1364     OStoreDirectory rStoreDir;
1365     if (rStoreDir.create(pTargetKey->getStoreFile(), sFullPath, keyName, KEY_MODE_CREATE))
1366     {
1367         return REG_CREATE_KEY_FAILED;
1368     }
1369 
1370     if (m_openKeyTable.count(sFullKeyName) > 0)
1371     {
1372         m_openKeyTable[sFullKeyName]->setDeleted(sal_False);
1373     }
1374 
1375     ORegKey* pTmpKey = 0;
1376     _ret = pSourceKey->openKey(keyName, (RegKeyHandle*)&pTmpKey);
1377     if (_ret != REG_NO_ERROR)
1378         return _ret;
1379 
1380     OStoreDirectory::iterator   iter;
1381     OStoreDirectory             rTmpStoreDir(pTmpKey->getStoreDir());
1382     storeError                  _err = rTmpStoreDir.first(iter);
1383 
1384     while ( _err == store_E_None)
1385     {
1386 		OUString const sName = iter.m_pszName;
1387 
1388         if (iter.m_nAttrib & STORE_ATTRIB_ISDIR)
1389         {
1390             _ret = loadAndSaveKeys(pTargetKey, pTmpKey,
1391                                    sName, nCut, bWarnings, bReport);
1392         } else
1393         {
1394             _ret = loadAndSaveValue(pTargetKey, pTmpKey,
1395                                     sName, nCut, bWarnings, bReport);
1396         }
1397 
1398         if (_ret == REG_MERGE_ERROR)
1399 			break;
1400 		if (_ret == REG_MERGE_CONFLICT && bWarnings)
1401 			break;
1402 
1403         _err = rTmpStoreDir.next(iter);
1404     }
1405 
1406     pSourceKey->releaseKey(pTmpKey);
1407     return _ret;
1408 }
1409 
1410 
1411 //*********************************************************************
1412 //  getRootKey()
1413 //
1414 ORegKey* ORegistry::getRootKey()
1415 {
1416     m_openKeyTable[ROOT]->acquire();
1417     return m_openKeyTable[ROOT];
1418 }
1419 
1420 
1421 //*********************************************************************
1422 //  dumpRegistry()
1423 //
1424 RegError ORegistry::dumpRegistry(RegKeyHandle hKey) const
1425 {
1426     ORegKey                     *pKey = (ORegKey*)hKey;
1427     OUString                    sName;
1428     RegError                    _ret = REG_NO_ERROR;
1429     OStoreDirectory::iterator   iter;
1430     OStoreDirectory             rStoreDir(pKey->getStoreDir());
1431     storeError                  _err = rStoreDir.first(iter);
1432 
1433 	OString regName( OUStringToOString( getName(), osl_getThreadTextEncoding() ) );
1434 	OString keyName( OUStringToOString( pKey->getName(), RTL_TEXTENCODING_UTF8 ) );
1435     fprintf(stdout, "Registry \"%s\":\n\n%s\n", regName.getStr(), keyName.getStr());
1436 
1437     while ( _err == store_E_None )
1438     {
1439         sName = iter.m_pszName;
1440 
1441         if (iter.m_nAttrib & STORE_ATTRIB_ISDIR)
1442         {
1443             _ret = dumpKey(pKey->getName(), sName, 1);
1444         } else
1445         {
1446             _ret = dumpValue(pKey->getName(), sName, 1);
1447         }
1448 
1449         if (_ret)
1450         {
1451             return _ret;
1452         }
1453 
1454         _err = rStoreDir.next(iter);
1455     }
1456 
1457     return REG_NO_ERROR;
1458 }
1459 
1460 //*********************************************************************
1461 //  dumpValue()
1462 //
1463 RegError ORegistry::dumpValue(const OUString& sPath, const OUString& sName, sal_Int16 nSpc) const
1464 {
1465     OStoreStream    rValue;
1466     sal_uInt8*      pBuffer;
1467     sal_uInt32      valueSize;
1468     RegValueType    valueType;
1469     OUString        sFullPath(sPath);
1470     OString         sIndent;
1471     storeAccessMode accessMode = VALUE_MODE_OPEN;
1472 
1473     if (isReadOnly())
1474     {
1475         accessMode = VALUE_MODE_OPENREAD;
1476     }
1477 
1478     for (int i= 0; i < nSpc; i++) sIndent += " ";
1479 
1480     if (sFullPath.getLength() > 1)
1481 	{
1482         sFullPath += ROOT;
1483 	}
1484     if (rValue.create(m_file, sFullPath, sName, accessMode))
1485     {
1486         return REG_VALUE_NOT_EXISTS;
1487     }
1488 
1489     pBuffer = (sal_uInt8*)rtl_allocateMemory(VALUE_HEADERSIZE);
1490 
1491     sal_uInt32  rwBytes;
1492     if (rValue.readAt(0, pBuffer, VALUE_HEADERSIZE, rwBytes))
1493     {
1494         rtl_freeMemory(pBuffer);
1495         return REG_INVALID_VALUE;
1496     }
1497     if (rwBytes != (VALUE_HEADERSIZE))
1498     {
1499         rtl_freeMemory(pBuffer);
1500         return REG_INVALID_VALUE;
1501     }
1502 
1503     sal_uInt8 type = *((sal_uInt8*)pBuffer);
1504     valueType = (RegValueType)type;
1505     readUINT32(pBuffer+VALUE_TYPEOFFSET, valueSize);
1506 
1507     pBuffer = (sal_uInt8*)rtl_allocateMemory(valueSize);
1508     if (rValue.readAt(VALUE_HEADEROFFSET, pBuffer, valueSize, rwBytes))
1509     {
1510         rtl_freeMemory(pBuffer);
1511         return REG_INVALID_VALUE;
1512     }
1513     if (rwBytes != valueSize)
1514     {
1515         rtl_freeMemory(pBuffer);
1516         return REG_INVALID_VALUE;
1517     }
1518 
1519     const sal_Char* indent = sIndent.getStr();
1520     switch (valueType)
1521     {
1522         case 0:
1523             fprintf(stdout, "%sValue: Type = VALUETYPE_NOT_DEFINED\n", indent);
1524             break;
1525         case 1:
1526             {
1527                 fprintf(stdout, "%sValue: Type = RG_VALUETYPE_LONG\n", indent);
1528                 fprintf(
1529                     stdout, "%s       Size = %lu\n", indent,
1530                     sal::static_int_cast< unsigned long >(valueSize));
1531                 fprintf(stdout, "%s       Data = ", indent);
1532 
1533                 sal_Int32 value;
1534                 readINT32(pBuffer, value);
1535                 fprintf(stdout, "%ld\n", sal::static_int_cast< long >(value));
1536             }
1537             break;
1538         case 2:
1539             {
1540                 sal_Char* value = (sal_Char*)rtl_allocateMemory(valueSize);
1541                 readUtf8(pBuffer, value, valueSize);
1542                 fprintf(stdout, "%sValue: Type = RG_VALUETYPE_STRING\n", indent);
1543                 fprintf(
1544                     stdout, "%s       Size = %lu\n", indent,
1545                     sal::static_int_cast< unsigned long >(valueSize));
1546                 fprintf(stdout, "%s       Data = \"%s\"\n", indent, value);
1547                 rtl_freeMemory(value);
1548             }
1549             break;
1550         case 3:
1551             {
1552                 sal_uInt32 size = (valueSize / 2) * sizeof(sal_Unicode);
1553                 fprintf(stdout, "%sValue: Type = RG_VALUETYPE_UNICODE\n", indent);
1554                 fprintf(
1555                     stdout, "%s       Size = %lu\n", indent,
1556                     sal::static_int_cast< unsigned long >(valueSize));
1557                 fprintf(stdout, "%s       Data = ", indent);
1558 
1559                 sal_Unicode* value = new sal_Unicode[size];
1560                 readString(pBuffer, value, size);
1561 
1562                 OString uStr = OUStringToOString(value, RTL_TEXTENCODING_UTF8);
1563                 fprintf(stdout, "L\"%s\"\n", uStr.getStr());
1564                 delete[] value;
1565             }
1566             break;
1567         case 4:
1568             {
1569                 fprintf(stdout, "%sValue: Type = RG_VALUETYPE_BINARY\n", indent);
1570                 fprintf(
1571                     stdout, "%s       Size = %lu\n", indent,
1572                     sal::static_int_cast< unsigned long >(valueSize));
1573                 fprintf(stdout, "%s       Data = ", indent);
1574                 dumpType(
1575                     typereg::Reader(
1576                         pBuffer, valueSize, false, TYPEREG_VERSION_1),
1577                     sIndent + "              ");
1578             }
1579             break;
1580         case 5:
1581             {
1582                 sal_uInt32 offset = 4; // initial 4 Bytes fuer die Laenge des Arrays
1583                 sal_uInt32 len = 0;
1584 
1585                 readUINT32(pBuffer, len);
1586 
1587                 fprintf(stdout, "%sValue: Type = RG_VALUETYPE_LONGLIST\n", indent);
1588                 fprintf(
1589                     stdout, "%s       Size = %lu\n", indent,
1590                     sal::static_int_cast< unsigned long >(valueSize));
1591                 fprintf(
1592                     stdout, "%s       Len  = %lu\n", indent,
1593                     sal::static_int_cast< unsigned long >(len));
1594                 fprintf(stdout, "%s       Data = ", indent);
1595 
1596                 sal_Int32 longValue;
1597                 for (sal_uInt32 i=0; i < len; i++)
1598                 {
1599                     readINT32(pBuffer+offset, longValue);
1600 
1601                     if (offset > 4)
1602                         fprintf(stdout, "%s              ", indent);
1603 
1604                     fprintf(
1605                         stdout, "%lu = %ld\n",
1606                         sal::static_int_cast< unsigned long >(i),
1607                         sal::static_int_cast< long >(longValue));
1608                     offset += 4; // 4 Bytes fuer sal_Int32
1609                 }
1610             }
1611             break;
1612         case 6:
1613             {
1614                 sal_uInt32 offset = 4; // initial 4 Bytes fuer die Laenge des Arrays
1615                 sal_uInt32 sLen = 0;
1616                 sal_uInt32 len = 0;
1617 
1618                 readUINT32(pBuffer, len);
1619 
1620                 fprintf(stdout, "%sValue: Type = RG_VALUETYPE_STRINGLIST\n", indent);
1621                 fprintf(
1622                     stdout, "%s       Size = %lu\n", indent,
1623                     sal::static_int_cast< unsigned long >(valueSize));
1624                 fprintf(
1625                     stdout, "%s       Len  = %lu\n", indent,
1626                     sal::static_int_cast< unsigned long >(len));
1627                 fprintf(stdout, "%s       Data = ", indent);
1628 
1629                 sal_Char *pValue;
1630                 for (sal_uInt32 i=0; i < len; i++)
1631                 {
1632                     readUINT32(pBuffer+offset, sLen);
1633 
1634                     offset += 4; // 4 Bytes (sal_uInt32) fuer die Groesse des strings in Bytes
1635 
1636                     pValue = (sal_Char*)rtl_allocateMemory(sLen);
1637                     readUtf8(pBuffer+offset, pValue, sLen);
1638 
1639                     if (offset > 8)
1640                         fprintf(stdout, "%s              ", indent);
1641 
1642                     fprintf(
1643                         stdout, "%lu = \"%s\"\n",
1644                         sal::static_int_cast< unsigned long >(i), pValue);
1645                     offset += sLen;
1646                 }
1647             }
1648             break;
1649         case 7:
1650             {
1651                 sal_uInt32 offset = 4; // initial 4 Bytes fuer die Laenge des Arrays
1652                 sal_uInt32 sLen = 0;
1653                 sal_uInt32 len = 0;
1654 
1655                 readUINT32(pBuffer, len);
1656 
1657                 fprintf(stdout, "%sValue: Type = RG_VALUETYPE_UNICODELIST\n", indent);
1658                 fprintf(
1659                     stdout, "%s       Size = %lu\n", indent,
1660                     sal::static_int_cast< unsigned long >(valueSize));
1661                 fprintf(
1662                     stdout, "%s       Len  = %lu\n", indent,
1663                     sal::static_int_cast< unsigned long >(len));
1664                 fprintf(stdout, "%s       Data = ", indent);
1665 
1666                 sal_Unicode *pValue;
1667                 OString uStr;
1668                 for (sal_uInt32 i=0; i < len; i++)
1669                 {
1670                     readUINT32(pBuffer+offset, sLen);
1671 
1672                     offset += 4; // 4 Bytes (sal_uInt32) fuer die Groesse des strings in Bytes
1673 
1674                     pValue = (sal_Unicode*)rtl_allocateMemory((sLen / 2) * sizeof(sal_Unicode));
1675                     readString(pBuffer+offset, pValue, sLen);
1676 
1677                     if (offset > 8)
1678                         fprintf(stdout, "%s              ", indent);
1679 
1680                     uStr = OUStringToOString(pValue, RTL_TEXTENCODING_UTF8);
1681                     fprintf(
1682                         stdout, "%lu = L\"%s\"\n",
1683                         sal::static_int_cast< unsigned long >(i),
1684                         uStr.getStr());
1685 
1686                     offset += sLen;
1687 
1688                     rtl_freeMemory(pValue);
1689                 }
1690             }
1691             break;
1692     }
1693 
1694     fprintf(stdout, "\n");
1695 
1696     rtl_freeMemory(pBuffer);
1697     return REG_NO_ERROR;
1698 }
1699 
1700 //*********************************************************************
1701 //  dumpKey()
1702 //
1703 RegError ORegistry::dumpKey(const OUString& sPath, const OUString& sName, sal_Int16 nSpace) const
1704 {
1705     OStoreDirectory 	rStoreDir;
1706     OUString          	sFullPath(sPath);
1707     OString             sIndent;
1708     storeAccessMode     accessMode = KEY_MODE_OPEN;
1709     RegError            _ret = REG_NO_ERROR;
1710 
1711     if (isReadOnly())
1712     {
1713         accessMode = KEY_MODE_OPENREAD;
1714     }
1715 
1716     for (int i= 0; i < nSpace; i++) sIndent += " ";
1717 
1718     if (sFullPath.getLength() > 1)
1719         sFullPath += ROOT;
1720 
1721     storeError _err = rStoreDir.create(m_file, sFullPath, sName, accessMode);
1722 
1723     if (_err == store_E_NotExists)
1724         return REG_KEY_NOT_EXISTS;
1725     else
1726     if (_err == store_E_WrongFormat)
1727         return REG_INVALID_KEY;
1728 
1729     fprintf(stdout, "%s/ %s\n", sIndent.getStr(), OUStringToOString(sName, RTL_TEXTENCODING_UTF8).getStr());
1730 
1731     OUString sSubPath(sFullPath);
1732     OUString sSubName;
1733     sSubPath += sName;
1734 
1735     OStoreDirectory::iterator   iter;
1736 
1737     _err = rStoreDir.first(iter);
1738 
1739     while ( _err == store_E_None)
1740     {
1741         sSubName = iter.m_pszName;
1742 
1743         if ( iter.m_nAttrib & STORE_ATTRIB_ISDIR )
1744         {
1745             _ret = dumpKey(sSubPath, sSubName, nSpace+2);
1746         } else
1747         {
1748             _ret = dumpValue(sSubPath, sSubName, nSpace+2);
1749         }
1750 
1751         if (_ret)
1752         {
1753             return _ret;
1754         }
1755 
1756         _err = rStoreDir.next(iter);
1757     }
1758 
1759     return REG_NO_ERROR;
1760 }
1761