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 #include "precompiled_stoc.hxx"
29 #include "sal/config.h"
30 
31 #include <cstdlib>
32 #include <memory>
33 #include <vector>
34 
35 #include "com/sun/star/lang/XServiceInfo.hpp"
36 #include "com/sun/star/registry/InvalidRegistryException.hpp"
37 #include "com/sun/star/registry/InvalidValueException.hpp"
38 #include "com/sun/star/registry/MergeConflictException.hpp"
39 #include "com/sun/star/registry/RegistryKeyType.hpp"
40 #include "com/sun/star/registry/XRegistryKey.hpp"
41 #include "com/sun/star/registry/XSimpleRegistry.hpp"
42 #include "com/sun/star/uno/Reference.hxx"
43 #include "com/sun/star/uno/RuntimeException.hpp"
44 #include "com/sun/star/uno/XComponentContext.hpp"
45 #include "com/sun/star/uno/XInterface.hpp"
46 #include "com/sun/star/uno/Sequence.hxx"
47 #include "cppuhelper/implbase1.hxx"
48 #include "cppuhelper/implbase2.hxx"
49 #include "cppuhelper/weak.hxx"
50 #include "osl/mutex.hxx"
51 #include "registry/registry.hxx"
52 #include "registry/regtype.h"
53 #include "rtl/ref.hxx"
54 #include "rtl/string.h"
55 #include "rtl/string.hxx"
56 #include "rtl/textcvt.h"
57 #include "rtl/textenc.h"
58 #include "rtl/unload.h"
59 #include "rtl/ustring.h"
60 #include "rtl/ustring.hxx"
61 #include "sal/types.h"
62 
63 #include "bootstrapservices.hxx"
64 
65 #include "textualservices.hxx"
66 
67 extern rtl_StandardModuleCount g_moduleCount;
68 
69 namespace {
70 
71 namespace css = com::sun::star;
72 
73 class SimpleRegistry:
74     public cppu::WeakImplHelper2<
75         css::registry::XSimpleRegistry, css::lang::XServiceInfo >
76 {
77 public:
78     SimpleRegistry() { g_moduleCount.modCnt.acquire(&g_moduleCount.modCnt); }
79 
80     ~SimpleRegistry() { g_moduleCount.modCnt.release(&g_moduleCount.modCnt); }
81 
82     osl::Mutex mutex_;
83 
84 private:
85     virtual rtl::OUString SAL_CALL getURL() throw (css::uno::RuntimeException);
86 
87     virtual void SAL_CALL open(
88         rtl::OUString const & rURL, sal_Bool bReadOnly, sal_Bool bCreate)
89         throw (
90             css::registry::InvalidRegistryException,
91             css::uno::RuntimeException);
92 
93     virtual sal_Bool SAL_CALL isValid() throw (css::uno::RuntimeException);
94 
95     virtual void SAL_CALL close() throw (
96         css::registry::InvalidRegistryException, css::uno::RuntimeException);
97 
98     virtual void SAL_CALL destroy() throw(
99         css::registry::InvalidRegistryException, css::uno::RuntimeException);
100 
101     virtual css::uno::Reference< css::registry::XRegistryKey > SAL_CALL
102     getRootKey() throw(
103         css::registry::InvalidRegistryException, css::uno::RuntimeException);
104 
105     virtual sal_Bool SAL_CALL isReadOnly() throw(
106         css::registry::InvalidRegistryException, css::uno::RuntimeException);
107 
108     virtual void SAL_CALL mergeKey(
109         rtl::OUString const & aKeyName, rtl::OUString const & aUrl)
110         throw (
111             css::registry::InvalidRegistryException,
112             css::registry::MergeConflictException, css::uno::RuntimeException);
113 
114     virtual rtl::OUString SAL_CALL getImplementationName()
115         throw (css::uno::RuntimeException)
116     { return stoc_bootstrap::simreg_getImplementationName(); }
117 
118     virtual sal_Bool SAL_CALL supportsService(rtl::OUString const & ServiceName)
119         throw (css::uno::RuntimeException)
120     { return ServiceName == getSupportedServiceNames()[0]; }
121 
122     virtual css::uno::Sequence< rtl::OUString > SAL_CALL
123     getSupportedServiceNames() throw (css::uno::RuntimeException)
124     { return stoc_bootstrap::simreg_getSupportedServiceNames(); }
125 
126     Registry registry_;
127     std::auto_ptr< stoc::simpleregistry::TextualServices > textual_;
128 };
129 
130 class Key: public cppu::WeakImplHelper1< css::registry::XRegistryKey > {
131 public:
132     Key(
133         rtl::Reference< SimpleRegistry > const & registry,
134         RegistryKey const & key):
135         registry_(registry), key_(key) {}
136 
137 private:
138     virtual rtl::OUString SAL_CALL getKeyName()
139         throw (css::uno::RuntimeException);
140 
141     virtual sal_Bool SAL_CALL isReadOnly() throw (
142         css::registry::InvalidRegistryException, css::uno::RuntimeException);
143 
144     virtual sal_Bool SAL_CALL isValid() throw(css::uno::RuntimeException);
145 
146     virtual css::registry::RegistryKeyType SAL_CALL getKeyType(
147         rtl::OUString const & rKeyName)
148         throw (
149             css::registry::InvalidRegistryException,
150             css::uno::RuntimeException);
151 
152     virtual css::registry::RegistryValueType SAL_CALL getValueType() throw(
153         css::registry::InvalidRegistryException, css::uno::RuntimeException);
154 
155     virtual sal_Int32 SAL_CALL getLongValue() throw (
156         css::registry::InvalidRegistryException,
157         css::registry::InvalidValueException, css::uno::RuntimeException);
158 
159     virtual void SAL_CALL setLongValue(sal_Int32 value) throw (
160         css::registry::InvalidRegistryException, css::uno::RuntimeException);
161 
162     virtual css::uno::Sequence< sal_Int32 > SAL_CALL getLongListValue() throw(
163         css::registry::InvalidRegistryException,
164         css::registry::InvalidValueException, css::uno::RuntimeException);
165 
166     virtual void SAL_CALL setLongListValue(
167         com::sun::star::uno::Sequence< sal_Int32 > const & seqValue)
168         throw (
169             css::registry::InvalidRegistryException,
170             css::uno::RuntimeException);
171 
172     virtual rtl::OUString SAL_CALL getAsciiValue() throw (
173         css::registry::InvalidRegistryException,
174         css::registry::InvalidValueException, css::uno::RuntimeException);
175 
176     virtual void SAL_CALL setAsciiValue(rtl::OUString const & value) throw (
177         css::registry::InvalidRegistryException, css::uno::RuntimeException);
178 
179     virtual css::uno::Sequence< rtl::OUString > SAL_CALL getAsciiListValue()
180         throw (
181             css::registry::InvalidRegistryException,
182             css::registry::InvalidValueException, css::uno::RuntimeException);
183 
184     virtual void SAL_CALL setAsciiListValue(
185         css::uno::Sequence< rtl::OUString > const & seqValue)
186         throw (
187             css::registry::InvalidRegistryException,
188             css::uno::RuntimeException);
189 
190     virtual rtl::OUString SAL_CALL getStringValue() throw(
191         css::registry::InvalidRegistryException,
192         css::registry::InvalidValueException, css::uno::RuntimeException);
193 
194     virtual void SAL_CALL setStringValue(rtl::OUString const & value) throw (
195         css::registry::InvalidRegistryException, css::uno::RuntimeException);
196 
197     virtual css::uno::Sequence< rtl::OUString > SAL_CALL getStringListValue()
198         throw (
199             css::registry::InvalidRegistryException,
200             css::registry::InvalidValueException, css::uno::RuntimeException);
201 
202     virtual void SAL_CALL setStringListValue(
203         css::uno::Sequence< rtl::OUString > const & seqValue)
204         throw (
205             css::registry::InvalidRegistryException,
206             css::uno::RuntimeException);
207 
208     virtual css::uno::Sequence< sal_Int8 > SAL_CALL getBinaryValue() throw (
209         css::registry::InvalidRegistryException,
210         css::registry::InvalidValueException, css::uno::RuntimeException);
211 
212     virtual void SAL_CALL setBinaryValue(
213         css::uno::Sequence< sal_Int8 > const & value)
214         throw (
215             css::registry::InvalidRegistryException,
216             css::uno::RuntimeException);
217 
218     virtual css::uno::Reference< css::registry::XRegistryKey > SAL_CALL openKey(
219         rtl::OUString const & aKeyName)
220         throw (
221             css::registry::InvalidRegistryException,
222             css::uno::RuntimeException);
223 
224     virtual css::uno::Reference< css::registry::XRegistryKey > SAL_CALL
225     createKey(rtl::OUString const & aKeyName) throw (
226         css::registry::InvalidRegistryException, css::uno::RuntimeException);
227 
228     virtual void SAL_CALL closeKey() throw (
229         css::registry::InvalidRegistryException, css::uno::RuntimeException);
230 
231     virtual void SAL_CALL deleteKey(rtl::OUString const & rKeyName) throw (
232         css::registry::InvalidRegistryException, css::uno::RuntimeException);
233 
234     virtual
235     css::uno::Sequence< css::uno::Reference< css::registry::XRegistryKey > >
236     SAL_CALL openKeys() throw (
237         css::registry::InvalidRegistryException, css::uno::RuntimeException);
238 
239     virtual css::uno::Sequence< rtl::OUString > SAL_CALL getKeyNames() throw (
240         css::registry::InvalidRegistryException, css::uno::RuntimeException);
241 
242     virtual sal_Bool SAL_CALL createLink(
243         rtl::OUString const & aLinkName, rtl::OUString const & aLinkTarget)
244         throw (
245             css::registry::InvalidRegistryException,
246             css::uno::RuntimeException);
247 
248     virtual void SAL_CALL deleteLink(rtl::OUString const & rLinkName) throw (
249         css::registry::InvalidRegistryException, css::uno::RuntimeException);
250 
251     virtual rtl::OUString SAL_CALL getLinkTarget(
252         rtl::OUString const & rLinkName)
253         throw (
254             css::registry::InvalidRegistryException,
255             css::uno::RuntimeException);
256 
257     virtual rtl::OUString SAL_CALL getResolvedName(
258         rtl::OUString const & aKeyName)
259         throw (
260             css::registry::InvalidRegistryException,
261             css::uno::RuntimeException);
262 
263     rtl::Reference< SimpleRegistry > registry_;
264     RegistryKey key_;
265 };
266 
267 rtl::OUString Key::getKeyName() throw (css::uno::RuntimeException) {
268     osl::MutexGuard guard(registry_->mutex_);
269     return key_.getName();
270 }
271 
272 sal_Bool Key::isReadOnly()
273     throw (css::registry::InvalidRegistryException, css::uno::RuntimeException)
274 {
275     osl::MutexGuard guard(registry_->mutex_);
276     return key_.isReadOnly();
277 }
278 
279 sal_Bool Key::isValid() throw (css::uno::RuntimeException) {
280     osl::MutexGuard guard(registry_->mutex_);
281     return key_.isValid();
282 }
283 
284 css::registry::RegistryKeyType Key::getKeyType(rtl::OUString const & rKeyName)
285     throw (css::registry::InvalidRegistryException, css::uno::RuntimeException)
286 {
287     osl::MutexGuard guard(registry_->mutex_);
288     RegKeyType type;
289     RegError err = key_.getKeyType(rKeyName, &type);
290     if (err != REG_NO_ERROR) {
291         throw css::registry::InvalidRegistryException(
292             (rtl::OUString(
293                 RTL_CONSTASCII_USTRINGPARAM(
294                     "com.sun.star.registry.SimpleRegistry key getKeyType:"
295                     " underlying RegistryKey::getKeyType() = ")) +
296              rtl::OUString::valueOf(static_cast< sal_Int32 >(err))),
297             static_cast< OWeakObject * >(this));
298     }
299     switch (type) {
300     default:
301         std::abort(); // this cannot happen
302         // pseudo-fall-through to avoid warnings on MSC
303     case RG_KEYTYPE:
304         return css::registry::RegistryKeyType_KEY;
305     case RG_LINKTYPE:
306         return css::registry::RegistryKeyType_LINK;
307     }
308 }
309 
310 css::registry::RegistryValueType Key::getValueType()
311     throw (css::registry::InvalidRegistryException, css::uno::RuntimeException)
312 {
313     osl::MutexGuard guard(registry_->mutex_);
314     RegValueType type;
315     sal_uInt32 size;
316     RegError err = key_.getValueInfo(rtl::OUString(), &type, &size);
317     switch (err) {
318     case REG_NO_ERROR:
319         break;
320     case REG_INVALID_VALUE:
321         type = RG_VALUETYPE_NOT_DEFINED;
322         break;
323     default:
324         throw css::registry::InvalidRegistryException(
325             (rtl::OUString(
326                 RTL_CONSTASCII_USTRINGPARAM(
327                     "com.sun.star.registry.SimpleRegistry key getValueType:"
328                     " underlying RegistryKey::getValueInfo() = ")) +
329              rtl::OUString::valueOf(static_cast< sal_Int32 >(err))),
330             static_cast< OWeakObject * >(this));
331     }
332     switch (type) {
333     default:
334         std::abort(); // this cannot happen
335         // pseudo-fall-through to avoid warnings on MSC
336     case RG_VALUETYPE_NOT_DEFINED:
337         return css::registry::RegistryValueType_NOT_DEFINED;
338     case RG_VALUETYPE_LONG:
339         return css::registry::RegistryValueType_LONG;
340     case RG_VALUETYPE_STRING:
341         return css::registry::RegistryValueType_ASCII;
342     case RG_VALUETYPE_UNICODE:
343         return css::registry::RegistryValueType_STRING;
344     case RG_VALUETYPE_BINARY:
345         return css::registry::RegistryValueType_BINARY;
346     case RG_VALUETYPE_LONGLIST:
347         return css::registry::RegistryValueType_LONGLIST;
348     case RG_VALUETYPE_STRINGLIST:
349         return css::registry::RegistryValueType_ASCIILIST;
350     case RG_VALUETYPE_UNICODELIST:
351         return css::registry::RegistryValueType_STRINGLIST;
352     }
353 }
354 
355 sal_Int32 Key::getLongValue() throw (
356     css::registry::InvalidRegistryException,
357     css::registry::InvalidValueException, css::uno::RuntimeException)
358 {
359     osl::MutexGuard guard(registry_->mutex_);
360     sal_Int32 value;
361     RegError err = key_.getValue(rtl::OUString(), &value);
362     switch (err) {
363     case REG_NO_ERROR:
364         break;
365     case REG_INVALID_VALUE:
366         throw css::registry::InvalidValueException(
367             rtl::OUString(
368                 RTL_CONSTASCII_USTRINGPARAM(
369                     "com.sun.star.registry.SimpleRegistry key getLongValue:"
370                     " underlying RegistryKey::getValue() = REG_INVALID_VALUE")),
371             static_cast< OWeakObject * >(this));
372     default:
373         throw css::registry::InvalidRegistryException(
374             (rtl::OUString(
375                 RTL_CONSTASCII_USTRINGPARAM(
376                     "com.sun.star.registry.SimpleRegistry key getLongValue:"
377                     " underlying RegistryKey::getValue() = ")) +
378              rtl::OUString::valueOf(static_cast< sal_Int32 >(err))),
379             static_cast< OWeakObject * >(this));
380     }
381     return value;
382 }
383 
384 void Key::setLongValue(sal_Int32 value)
385     throw (css::registry::InvalidRegistryException, css::uno::RuntimeException)
386 {
387     osl::MutexGuard guard(registry_->mutex_);
388     RegError err = key_.setValue(
389         rtl::OUString(), RG_VALUETYPE_LONG, &value, sizeof (sal_Int32));
390     if (err != REG_NO_ERROR) {
391         throw css::registry::InvalidRegistryException(
392             (rtl::OUString(
393                 RTL_CONSTASCII_USTRINGPARAM(
394                     "com.sun.star.registry.SimpleRegistry key setLongValue:"
395                     " underlying RegistryKey::setValue() = ")) +
396              rtl::OUString::valueOf(static_cast< sal_Int32 >(err))),
397             static_cast< OWeakObject * >(this));
398     }
399 }
400 
401 css::uno::Sequence< sal_Int32 > Key::getLongListValue() throw (
402     css::registry::InvalidRegistryException,
403     css::registry::InvalidValueException, css::uno::RuntimeException)
404 {
405     osl::MutexGuard guard(registry_->mutex_);
406     RegistryValueList< sal_Int32 > list;
407     RegError err = key_.getLongListValue(rtl::OUString(), list);
408     switch (err) {
409     case REG_NO_ERROR:
410         break;
411     case REG_VALUE_NOT_EXISTS:
412         return css::uno::Sequence< sal_Int32 >();
413     case REG_INVALID_VALUE:
414         throw css::registry::InvalidValueException(
415             rtl::OUString(
416                 RTL_CONSTASCII_USTRINGPARAM(
417                     "com.sun.star.registry.SimpleRegistry key getLongListValue:"
418                     " underlying RegistryKey::getLongListValue() ="
419                     " REG_INVALID_VALUE")),
420             static_cast< OWeakObject * >(this));
421     default:
422         throw css::registry::InvalidRegistryException(
423             (rtl::OUString(
424                 RTL_CONSTASCII_USTRINGPARAM(
425                     "com.sun.star.registry.SimpleRegistry key getLongListValue:"
426                     " underlying RegistryKey::getLongListValue() = ")) +
427              rtl::OUString::valueOf(static_cast< sal_Int32 >(err))),
428             static_cast< OWeakObject * >(this));
429     }
430     sal_uInt32 n = list.getLength();
431     if (n > SAL_MAX_INT32) {
432         throw css::registry::InvalidValueException(
433             rtl::OUString(
434                 RTL_CONSTASCII_USTRINGPARAM(
435                     "com.sun.star.registry.SimpleRegistry key getLongListValue:"
436                     " underlying RegistryKey::getLongListValue() too large")),
437             static_cast< OWeakObject * >(this));
438     }
439     css::uno::Sequence< sal_Int32 > value(static_cast< sal_Int32 >(n));
440     for (sal_uInt32 i = 0; i < n; ++i) {
441         value[static_cast< sal_Int32 >(i)] = list.getElement(i);
442     }
443     return value;
444 }
445 
446 void Key::setLongListValue(css::uno::Sequence< sal_Int32 > const & seqValue)
447     throw (css::registry::InvalidRegistryException, css::uno::RuntimeException)
448 {
449     osl::MutexGuard guard(registry_->mutex_);
450     std::vector< sal_Int32 > list;
451     for (sal_Int32 i = 0; i < seqValue.getLength(); ++i) {
452         list.push_back(seqValue[i]);
453     }
454     RegError err = key_.setLongListValue(
455         rtl::OUString(), list.empty() ? 0 : &list[0],
456         static_cast< sal_uInt32 >(list.size()));
457     if (err != REG_NO_ERROR) {
458         throw css::registry::InvalidRegistryException(
459             (rtl::OUString(
460                 RTL_CONSTASCII_USTRINGPARAM(
461                     "com.sun.star.registry.SimpleRegistry key setLongListValue:"
462                     " underlying RegistryKey::setLongListValue() = ")) +
463              rtl::OUString::valueOf(static_cast< sal_Int32 >(err))),
464             static_cast< OWeakObject * >(this));
465     }
466 }
467 
468 rtl::OUString Key::getAsciiValue() throw (
469     css::registry::InvalidRegistryException,
470     css::registry::InvalidValueException, css::uno::RuntimeException)
471 {
472     osl::MutexGuard guard(registry_->mutex_);
473     RegValueType type;
474     sal_uInt32 size;
475     RegError err = key_.getValueInfo(rtl::OUString(), &type, &size);
476     if (err != REG_NO_ERROR) {
477         throw css::registry::InvalidRegistryException(
478             (rtl::OUString(
479                 RTL_CONSTASCII_USTRINGPARAM(
480                     "com.sun.star.registry.SimpleRegistry key getAsciiValue:"
481                     " underlying RegistryKey::getValueInfo() = ")) +
482              rtl::OUString::valueOf(static_cast< sal_Int32 >(err))),
483             static_cast< OWeakObject * >(this));
484     }
485     if (type != RG_VALUETYPE_STRING) {
486         throw css::registry::InvalidValueException(
487             (rtl::OUString(
488                 RTL_CONSTASCII_USTRINGPARAM(
489                     "com.sun.star.registry.SimpleRegistry key getAsciiValue:"
490                     " underlying RegistryKey type = ")) +
491              rtl::OUString::valueOf(static_cast< sal_Int32 >(type))),
492             static_cast< OWeakObject * >(this));
493     }
494     // size contains terminating null (error in underlying registry.cxx):
495     if (size == 0) {
496         throw css::registry::InvalidValueException(
497             rtl::OUString(
498                 RTL_CONSTASCII_USTRINGPARAM(
499                     "com.sun.star.registry.SimpleRegistry key getAsciiValue:"
500                     " underlying RegistryKey size 0 cannot happen due to"
501                     " design error")),
502             static_cast< OWeakObject * >(this));
503     }
504     if (size > SAL_MAX_INT32) {
505         throw css::registry::InvalidValueException(
506             rtl::OUString(
507                 RTL_CONSTASCII_USTRINGPARAM(
508                     "com.sun.star.registry.SimpleRegistry key getAsciiValue:"
509                     " underlying RegistryKey size too large")),
510             static_cast< OWeakObject * >(this));
511     }
512     std::vector< char > list(size);
513     err = key_.getValue(rtl::OUString(), &list[0]);
514     if (err != REG_NO_ERROR) {
515         throw css::registry::InvalidRegistryException(
516             (rtl::OUString(
517                 RTL_CONSTASCII_USTRINGPARAM(
518                     "com.sun.star.registry.SimpleRegistry key getAsciiValue:"
519                     " underlying RegistryKey::getValue() = ")) +
520              rtl::OUString::valueOf(static_cast< sal_Int32 >(err))),
521             static_cast< OWeakObject * >(this));
522     }
523     if (list[size - 1] != '\0') {
524         throw css::registry::InvalidValueException(
525             rtl::OUString(
526                 RTL_CONSTASCII_USTRINGPARAM(
527                     "com.sun.star.registry.SimpleRegistry key getAsciiValue:"
528                     " underlying RegistryKey value must be null-terminated due"
529                     " to design error")),
530             static_cast< OWeakObject * >(this));
531     }
532     rtl::OUString value;
533     if (!rtl_convertStringToUString(
534             &value.pData, &list[0],
535             static_cast< sal_Int32 >(size - 1), RTL_TEXTENCODING_UTF8,
536             (RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR |
537              RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR |
538              RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR)))
539     {
540         throw css::registry::InvalidValueException(
541             rtl::OUString(
542                 RTL_CONSTASCII_USTRINGPARAM(
543                     "com.sun.star.registry.SimpleRegistry key getAsciiValue:"
544                     " underlying RegistryKey not UTF-8")),
545             static_cast< OWeakObject * >(this));
546     }
547     return value;
548 }
549 
550 void Key::setAsciiValue(rtl::OUString const & value)
551     throw (css::registry::InvalidRegistryException, css::uno::RuntimeException)
552 {
553     osl::MutexGuard guard(registry_->mutex_);
554     rtl::OString utf8;
555     if (!value.convertToString(
556             &utf8, RTL_TEXTENCODING_UTF8,
557             (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR |
558              RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR)))
559     {
560         throw css::uno::RuntimeException(
561             rtl::OUString(
562                 RTL_CONSTASCII_USTRINGPARAM(
563                     "com.sun.star.registry.SimpleRegistry key setAsciiValue:"
564                     " value not UTF-16")),
565             static_cast< OWeakObject * >(this));
566     }
567     RegError err = key_.setValue(
568         rtl::OUString(), RG_VALUETYPE_STRING,
569         const_cast< char * >(utf8.getStr()), utf8.getLength() + 1);
570         // +1 for terminating null (error in underlying registry.cxx)
571     if (err != REG_NO_ERROR) {
572         throw css::registry::InvalidRegistryException(
573             (rtl::OUString(
574                 RTL_CONSTASCII_USTRINGPARAM(
575                     "com.sun.star.registry.SimpleRegistry key setAsciiValue:"
576                     " underlying RegistryKey::setValue() = ")) +
577              rtl::OUString::valueOf(static_cast< sal_Int32 >(err))),
578             static_cast< OWeakObject * >(this));
579     }
580 }
581 
582 css::uno::Sequence< rtl::OUString > Key::getAsciiListValue() throw (
583     css::registry::InvalidRegistryException,
584     css::registry::InvalidValueException, css::uno::RuntimeException)
585 {
586     osl::MutexGuard guard(registry_->mutex_);
587     RegistryValueList< char * > list;
588     RegError err = key_.getStringListValue(rtl::OUString(), list);
589     switch (err) {
590     case REG_NO_ERROR:
591         break;
592     case REG_VALUE_NOT_EXISTS:
593         return css::uno::Sequence< rtl::OUString >();
594     case REG_INVALID_VALUE:
595         throw css::registry::InvalidValueException(
596             rtl::OUString(
597                 RTL_CONSTASCII_USTRINGPARAM(
598                     "com.sun.star.registry.SimpleRegistry key"
599                     " getAsciiListValue: underlying"
600                     " RegistryKey::getStringListValue() = REG_INVALID_VALUE")),
601             static_cast< OWeakObject * >(this));
602     default:
603         throw css::registry::InvalidRegistryException(
604             (rtl::OUString(
605                 RTL_CONSTASCII_USTRINGPARAM(
606                     "com.sun.star.registry.SimpleRegistry key"
607                     " getAsciiListValue: underlying"
608                     " RegistryKey::getStringListValue() = ")) +
609              rtl::OUString::valueOf(static_cast< sal_Int32 >(err))),
610             static_cast< OWeakObject * >(this));
611     }
612     sal_uInt32 n = list.getLength();
613     if (n > SAL_MAX_INT32) {
614         throw css::registry::InvalidValueException(
615             rtl::OUString(
616                 RTL_CONSTASCII_USTRINGPARAM(
617                     "com.sun.star.registry.SimpleRegistry key"
618                     " getAsciiListValue: underlying"
619                     " RegistryKey::getStringListValue() too large")),
620             static_cast< OWeakObject * >(this));
621     }
622     css::uno::Sequence< rtl::OUString > value(static_cast< sal_Int32 >(n));
623     for (sal_uInt32 i = 0; i < n; ++i) {
624         char * el = list.getElement(i);
625         sal_Int32 size = rtl_str_getLength(el);
626         if (!rtl_convertStringToUString(
627                 &value[static_cast< sal_Int32 >(i)].pData, el, size,
628                 RTL_TEXTENCODING_UTF8,
629                 (RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR |
630                  RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR |
631                  RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR)))
632         {
633             throw css::registry::InvalidValueException(
634                 rtl::OUString(
635                     RTL_CONSTASCII_USTRINGPARAM(
636                         "com.sun.star.registry.SimpleRegistry key"
637                         " getAsciiListValue: underlying RegistryKey not"
638                         " UTF-8")),
639                 static_cast< OWeakObject * >(this));
640         }
641     }
642     return value;
643 }
644 
645 void Key::setAsciiListValue(
646     css::uno::Sequence< rtl::OUString > const & seqValue)
647     throw (css::registry::InvalidRegistryException, css::uno::RuntimeException)
648 {
649     osl::MutexGuard guard(registry_->mutex_);
650     std::vector< rtl::OString > list;
651     for (sal_Int32 i = 0; i < seqValue.getLength(); ++i) {
652         rtl::OString utf8;
653         if (!seqValue[i].convertToString(
654                 &utf8, RTL_TEXTENCODING_UTF8,
655                 (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR |
656                  RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR)))
657         {
658             throw css::uno::RuntimeException(
659                 rtl::OUString(
660                     RTL_CONSTASCII_USTRINGPARAM(
661                         "com.sun.star.registry.SimpleRegistry key"
662                         " setAsciiListValue: value not UTF-16")),
663                 static_cast< OWeakObject * >(this));
664         }
665         list.push_back(utf8);
666     }
667     std::vector< char * > list2;
668     for (std::vector< rtl::OString >::iterator i(list.begin()); i != list.end();
669          ++i)
670     {
671         list2.push_back(const_cast< char * >(i->getStr()));
672     }
673     RegError err = key_.setStringListValue(
674         rtl::OUString(), list2.empty() ? 0 : &list2[0],
675         static_cast< sal_uInt32 >(list2.size()));
676     if (err != REG_NO_ERROR) {
677         throw css::registry::InvalidRegistryException(
678             (rtl::OUString(
679                 RTL_CONSTASCII_USTRINGPARAM(
680                     "com.sun.star.registry.SimpleRegistry key"
681                     " setAsciiListValue: underlying"
682                     " RegistryKey::setStringListValue() = ")) +
683              rtl::OUString::valueOf(static_cast< sal_Int32 >(err))),
684             static_cast< OWeakObject * >(this));
685     }
686 }
687 
688 rtl::OUString Key::getStringValue() throw (
689     css::registry::InvalidRegistryException,
690     css::registry::InvalidValueException, css::uno::RuntimeException)
691 {
692     osl::MutexGuard guard(registry_->mutex_);
693     RegValueType type;
694     sal_uInt32 size;
695     RegError err = key_.getValueInfo(rtl::OUString(), &type, &size);
696     if (err != REG_NO_ERROR) {
697         throw css::registry::InvalidRegistryException(
698             (rtl::OUString(
699                 RTL_CONSTASCII_USTRINGPARAM(
700                     "com.sun.star.registry.SimpleRegistry key getStringValue:"
701                     " underlying RegistryKey::getValueInfo() = ")) +
702              rtl::OUString::valueOf(static_cast< sal_Int32 >(err))),
703             static_cast< OWeakObject * >(this));
704     }
705     if (type != RG_VALUETYPE_UNICODE) {
706         throw css::registry::InvalidValueException(
707             (rtl::OUString(
708                 RTL_CONSTASCII_USTRINGPARAM(
709                     "com.sun.star.registry.SimpleRegistry key getStringValue:"
710                     " underlying RegistryKey type = ")) +
711              rtl::OUString::valueOf(static_cast< sal_Int32 >(type))),
712             static_cast< OWeakObject * >(this));
713     }
714     // size contains terminating null and is *2 (error in underlying
715     // registry.cxx):
716     if (size == 0 || (size & 1) == 1) {
717         throw css::registry::InvalidValueException(
718             rtl::OUString(
719                 RTL_CONSTASCII_USTRINGPARAM(
720                     "com.sun.star.registry.SimpleRegistry key getStringValue:"
721                     " underlying RegistryKey size 0 or odd cannot happen due to"
722                     " design error")),
723             static_cast< OWeakObject * >(this));
724     }
725     if (size > SAL_MAX_INT32) {
726         throw css::registry::InvalidValueException(
727             rtl::OUString(
728                 RTL_CONSTASCII_USTRINGPARAM(
729                     "com.sun.star.registry.SimpleRegistry key getStringValue:"
730                     " underlying RegistryKey size too large")),
731             static_cast< OWeakObject * >(this));
732     }
733     std::vector< sal_Unicode > list(size);
734     err = key_.getValue(rtl::OUString(), &list[0]);
735     if (err != REG_NO_ERROR) {
736         throw css::registry::InvalidRegistryException(
737             (rtl::OUString(
738                 RTL_CONSTASCII_USTRINGPARAM(
739                     "com.sun.star.registry.SimpleRegistry key getStringValue:"
740                     " underlying RegistryKey::getValue() = ")) +
741              rtl::OUString::valueOf(static_cast< sal_Int32 >(err))),
742             static_cast< OWeakObject * >(this));
743     }
744     if (list[size/2 - 1] != 0) {
745         throw css::registry::InvalidValueException(
746             rtl::OUString(
747                 RTL_CONSTASCII_USTRINGPARAM(
748                     "com.sun.star.registry.SimpleRegistry key getStringValue:"
749                     " underlying RegistryKey value must be null-terminated due"
750                     " to design error")),
751             static_cast< OWeakObject * >(this));
752     }
753     return rtl::OUString(&list[0], static_cast< sal_Int32 >(size/2 - 1));
754 }
755 
756 void Key::setStringValue(rtl::OUString const & value)
757     throw (css::registry::InvalidRegistryException, css::uno::RuntimeException)
758 {
759     osl::MutexGuard guard(registry_->mutex_);
760     RegError err = key_.setValue(
761         rtl::OUString(), RG_VALUETYPE_UNICODE,
762         const_cast< sal_Unicode * >(value.getStr()),
763         (value.getLength() + 1) * sizeof (sal_Unicode));
764         // +1 for terminating null (error in underlying registry.cxx)
765     if (err != REG_NO_ERROR) {
766         throw css::registry::InvalidRegistryException(
767             (rtl::OUString(
768                 RTL_CONSTASCII_USTRINGPARAM(
769                     "com.sun.star.registry.SimpleRegistry key setStringValue:"
770                     " underlying RegistryKey::setValue() = ")) +
771              rtl::OUString::valueOf(static_cast< sal_Int32 >(err))),
772             static_cast< OWeakObject * >(this));
773     }
774 }
775 
776 css::uno::Sequence< rtl::OUString > Key::getStringListValue() throw (
777     css::registry::InvalidRegistryException,
778     css::registry::InvalidValueException, css::uno::RuntimeException)
779 {
780     osl::MutexGuard guard(registry_->mutex_);
781     RegistryValueList< sal_Unicode * > list;
782     RegError err = key_.getUnicodeListValue(rtl::OUString(), list);
783     switch (err) {
784     case REG_NO_ERROR:
785         break;
786     case REG_VALUE_NOT_EXISTS:
787         return css::uno::Sequence< rtl::OUString >();
788     case REG_INVALID_VALUE:
789         throw css::registry::InvalidValueException(
790             rtl::OUString(
791                 RTL_CONSTASCII_USTRINGPARAM(
792                     "com.sun.star.registry.SimpleRegistry key"
793                     " getStringListValue: underlying"
794                     " RegistryKey::getUnicodeListValue() = REG_INVALID_VALUE")),
795             static_cast< OWeakObject * >(this));
796     default:
797         throw css::registry::InvalidRegistryException(
798             (rtl::OUString(
799                 RTL_CONSTASCII_USTRINGPARAM(
800                     "com.sun.star.registry.SimpleRegistry key"
801                     " getStringListValue: underlying"
802                     " RegistryKey::getUnicodeListValue() = ")) +
803              rtl::OUString::valueOf(static_cast< sal_Int32 >(err))),
804             static_cast< OWeakObject * >(this));
805     }
806     sal_uInt32 n = list.getLength();
807     if (n > SAL_MAX_INT32) {
808         throw css::registry::InvalidValueException(
809             rtl::OUString(
810                 RTL_CONSTASCII_USTRINGPARAM(
811                     "com.sun.star.registry.SimpleRegistry key"
812                     " getStringListValue: underlying"
813                     " RegistryKey::getUnicodeListValue() too large")),
814             static_cast< OWeakObject * >(this));
815     }
816     css::uno::Sequence< rtl::OUString > value(static_cast< sal_Int32 >(n));
817     for (sal_uInt32 i = 0; i < n; ++i) {
818         value[static_cast< sal_Int32 >(i)] = list.getElement(i);
819     }
820     return value;
821 }
822 
823 void Key::setStringListValue(
824     css::uno::Sequence< rtl::OUString > const & seqValue)
825     throw (css::registry::InvalidRegistryException, css::uno::RuntimeException)
826 {
827     osl::MutexGuard guard(registry_->mutex_);
828     std::vector< sal_Unicode * > list;
829     for (sal_Int32 i = 0; i < seqValue.getLength(); ++i) {
830         list.push_back(const_cast< sal_Unicode * >(seqValue[i].getStr()));
831     }
832     RegError err = key_.setUnicodeListValue(
833         rtl::OUString(), list.empty() ? 0 : &list[0],
834         static_cast< sal_uInt32 >(list.size()));
835     if (err != REG_NO_ERROR) {
836         throw css::registry::InvalidRegistryException(
837             (rtl::OUString(
838                 RTL_CONSTASCII_USTRINGPARAM(
839                     "com.sun.star.registry.SimpleRegistry key"
840                     " setStringListValue: underlying"
841                     " RegistryKey::setUnicodeListValue() = ")) +
842              rtl::OUString::valueOf(static_cast< sal_Int32 >(err))),
843             static_cast< OWeakObject * >(this));
844     }
845 }
846 
847 css::uno::Sequence< sal_Int8 > Key::getBinaryValue()
848     throw (
849         css::registry::InvalidRegistryException,
850         css::registry::InvalidValueException, css::uno::RuntimeException)
851 {
852     osl::MutexGuard guard(registry_->mutex_);
853     RegValueType type;
854     sal_uInt32 size;
855     RegError err = key_.getValueInfo(rtl::OUString(), &type, &size);
856     if (err != REG_NO_ERROR) {
857         throw css::registry::InvalidRegistryException(
858             (rtl::OUString(
859                 RTL_CONSTASCII_USTRINGPARAM(
860                     "com.sun.star.registry.SimpleRegistry key getBinaryValue:"
861                     " underlying RegistryKey::getValueInfo() = ")) +
862              rtl::OUString::valueOf(static_cast< sal_Int32 >(err))),
863             static_cast< OWeakObject * >(this));
864     }
865     if (type != RG_VALUETYPE_BINARY) {
866         throw css::registry::InvalidValueException(
867             (rtl::OUString(
868                 RTL_CONSTASCII_USTRINGPARAM(
869                     "com.sun.star.registry.SimpleRegistry key getBinaryValue:"
870                     " underlying RegistryKey type = ")) +
871              rtl::OUString::valueOf(static_cast< sal_Int32 >(type))),
872             static_cast< OWeakObject * >(this));
873     }
874     if (size > SAL_MAX_INT32) {
875         throw css::registry::InvalidValueException(
876             rtl::OUString(
877                 RTL_CONSTASCII_USTRINGPARAM(
878                     "com.sun.star.registry.SimpleRegistry key getBinaryValue:"
879                     " underlying RegistryKey size too large")),
880             static_cast< OWeakObject * >(this));
881     }
882     css::uno::Sequence< sal_Int8 > value(static_cast< sal_Int32 >(size));
883     err = key_.getValue(rtl::OUString(), value.getArray());
884     if (err != REG_NO_ERROR) {
885         throw css::registry::InvalidRegistryException(
886             (rtl::OUString(
887                 RTL_CONSTASCII_USTRINGPARAM(
888                     "com.sun.star.registry.SimpleRegistry key getBinaryValue:"
889                     " underlying RegistryKey::getValue() = ")) +
890              rtl::OUString::valueOf(static_cast< sal_Int32 >(err))),
891             static_cast< OWeakObject * >(this));
892     }
893     return value;
894 }
895 
896 void Key::setBinaryValue(css::uno::Sequence< sal_Int8 > const & value)
897     throw (css::registry::InvalidRegistryException, css::uno::RuntimeException)
898 {
899     osl::MutexGuard guard(registry_->mutex_);
900     RegError err = key_.setValue(
901         rtl::OUString(), RG_VALUETYPE_BINARY,
902         const_cast< sal_Int8 * >(value.getConstArray()),
903         static_cast< sal_uInt32 >(value.getLength()));
904     if (err != REG_NO_ERROR) {
905         throw css::registry::InvalidRegistryException(
906             (rtl::OUString(
907                 RTL_CONSTASCII_USTRINGPARAM(
908                     "com.sun.star.registry.SimpleRegistry key setBinaryValue:"
909                     " underlying RegistryKey::setValue() = ")) +
910              rtl::OUString::valueOf(static_cast< sal_Int32 >(err))),
911             static_cast< OWeakObject * >(this));
912     }
913 }
914 
915 css::uno::Reference< css::registry::XRegistryKey > Key::openKey(
916     rtl::OUString const & aKeyName)
917     throw (css::registry::InvalidRegistryException, css::uno::RuntimeException)
918 {
919     osl::MutexGuard guard(registry_->mutex_);
920     RegistryKey key;
921     RegError err = key_.openKey(aKeyName, key);
922     switch (err) {
923     case REG_NO_ERROR:
924         return new Key(registry_, key);
925     case REG_KEY_NOT_EXISTS:
926         return css::uno::Reference< css::registry::XRegistryKey >();
927     default:
928         throw css::registry::InvalidRegistryException(
929             (rtl::OUString(
930                 RTL_CONSTASCII_USTRINGPARAM(
931                     "com.sun.star.registry.SimpleRegistry key openKey:"
932                     " underlying RegistryKey::openKey() = ")) +
933              rtl::OUString::valueOf(static_cast< sal_Int32 >(err))),
934             static_cast< OWeakObject * >(this));
935     }
936 }
937 
938 css::uno::Reference< css::registry::XRegistryKey > Key::createKey(
939     rtl::OUString const & aKeyName)
940     throw (css::registry::InvalidRegistryException, css::uno::RuntimeException)
941 {
942     osl::MutexGuard guard(registry_->mutex_);
943     RegistryKey key;
944     RegError err = key_.createKey(aKeyName, key);
945     switch (err) {
946     case REG_NO_ERROR:
947         return new Key(registry_, key);
948     case REG_INVALID_KEYNAME:
949         return css::uno::Reference< css::registry::XRegistryKey >();
950     default:
951         throw css::registry::InvalidRegistryException(
952             (rtl::OUString(
953                 RTL_CONSTASCII_USTRINGPARAM(
954                     "com.sun.star.registry.SimpleRegistry key createKey:"
955                     " underlying RegistryKey::createKey() = ")) +
956              rtl::OUString::valueOf(static_cast< sal_Int32 >(err))),
957             static_cast< OWeakObject * >(this));
958     }
959 }
960 
961 void Key::closeKey()
962     throw (css::registry::InvalidRegistryException, css::uno::RuntimeException)
963 {
964     osl::MutexGuard guard(registry_->mutex_);
965     RegError err = key_.closeKey();
966     if (err != REG_NO_ERROR) {
967         throw css::registry::InvalidRegistryException(
968             (rtl::OUString(
969                 RTL_CONSTASCII_USTRINGPARAM(
970                     "com.sun.star.registry.SimpleRegistry key closeKey:"
971                     " underlying RegistryKey::closeKey() = ")) +
972              rtl::OUString::valueOf(static_cast< sal_Int32 >(err))),
973             static_cast< OWeakObject * >(this));
974     }
975 }
976 
977 void Key::deleteKey(rtl::OUString const & rKeyName)
978     throw (css::registry::InvalidRegistryException, css::uno::RuntimeException)
979 {
980     osl::MutexGuard guard(registry_->mutex_);
981     RegError err = key_.deleteKey(rKeyName);
982     if (err != REG_NO_ERROR) {
983         throw css::registry::InvalidRegistryException(
984             (rtl::OUString(
985                 RTL_CONSTASCII_USTRINGPARAM(
986                     "com.sun.star.registry.SimpleRegistry key deleteKey:"
987                     " underlying RegistryKey::deleteKey() = ")) +
988              rtl::OUString::valueOf(static_cast< sal_Int32 >(err))),
989             static_cast< OWeakObject * >(this));
990     }
991 }
992 
993 css::uno::Sequence< css::uno::Reference< css::registry::XRegistryKey > >
994 Key::openKeys()
995     throw (css::registry::InvalidRegistryException, css::uno::RuntimeException)
996 {
997     osl::MutexGuard guard(registry_->mutex_);
998     RegistryKeyArray list;
999     RegError err = key_.openSubKeys(rtl::OUString(), list);
1000     if (err != REG_NO_ERROR) {
1001         throw css::registry::InvalidRegistryException(
1002             (rtl::OUString(
1003                 RTL_CONSTASCII_USTRINGPARAM(
1004                     "com.sun.star.registry.SimpleRegistry key openKeys:"
1005                     " underlying RegistryKey::openSubKeys() = ")) +
1006              rtl::OUString::valueOf(static_cast< sal_Int32 >(err))),
1007             static_cast< OWeakObject * >(this));
1008     }
1009     sal_uInt32 n = list.getLength();
1010     if (n > SAL_MAX_INT32) {
1011         throw css::registry::InvalidRegistryException(
1012             rtl::OUString(
1013                 RTL_CONSTASCII_USTRINGPARAM(
1014                     "com.sun.star.registry.SimpleRegistry key getKeyNames:"
1015                     " underlying RegistryKey::getKeyNames() too large")),
1016             static_cast< OWeakObject * >(this));
1017     }
1018     css::uno::Sequence< css::uno::Reference< css::registry::XRegistryKey > >
1019         keys(static_cast< sal_Int32 >(n));
1020     for (sal_uInt32 i = 0; i < n; ++i) {
1021         keys[static_cast< sal_Int32 >(i)] = new Key(
1022             registry_, list.getElement(i));
1023     }
1024     return keys;
1025 }
1026 
1027 css::uno::Sequence< rtl::OUString > Key::getKeyNames()
1028     throw (css::registry::InvalidRegistryException, css::uno::RuntimeException)
1029 {
1030     osl::MutexGuard guard(registry_->mutex_);
1031     RegistryKeyNames list;
1032     RegError err = key_.getKeyNames(rtl::OUString(), list);
1033     if (err != REG_NO_ERROR) {
1034         throw css::registry::InvalidRegistryException(
1035             (rtl::OUString(
1036                 RTL_CONSTASCII_USTRINGPARAM(
1037                     "com.sun.star.registry.SimpleRegistry key getKeyNames:"
1038                     " underlying RegistryKey::getKeyNames() = ")) +
1039              rtl::OUString::valueOf(static_cast< sal_Int32 >(err))),
1040             static_cast< OWeakObject * >(this));
1041     }
1042     sal_uInt32 n = list.getLength();
1043     if (n > SAL_MAX_INT32) {
1044         throw css::registry::InvalidRegistryException(
1045             rtl::OUString(
1046                 RTL_CONSTASCII_USTRINGPARAM(
1047                     "com.sun.star.registry.SimpleRegistry key getKeyNames:"
1048                     " underlying RegistryKey::getKeyNames() too large")),
1049             static_cast< OWeakObject * >(this));
1050     }
1051     css::uno::Sequence< rtl::OUString > names(static_cast< sal_Int32 >(n));
1052     for (sal_uInt32 i = 0; i < n; ++i) {
1053         names[static_cast< sal_Int32 >(i)] = list.getElement(i);
1054     }
1055     return names;
1056 }
1057 
1058 sal_Bool Key::createLink(
1059     rtl::OUString const & aLinkName, rtl::OUString const & aLinkTarget)
1060     throw (css::registry::InvalidRegistryException, css::uno::RuntimeException)
1061 {
1062     osl::MutexGuard guard(registry_->mutex_);
1063     RegError err = key_.createLink(aLinkName, aLinkTarget);
1064     switch (err) {
1065     case REG_NO_ERROR:
1066         return true;
1067     case REG_INVALID_KEY:
1068     case REG_DETECT_RECURSION:
1069         throw css::registry::InvalidRegistryException(
1070             (rtl::OUString(
1071                 RTL_CONSTASCII_USTRINGPARAM(
1072                     "com.sun.star.registry.SimpleRegistry key createLink:"
1073                     " underlying RegistryKey::createLink() = ")) +
1074              rtl::OUString::valueOf(static_cast< sal_Int32 >(err))),
1075             static_cast< OWeakObject * >(this));
1076     default:
1077         return false;
1078     }
1079 }
1080 
1081 void Key::deleteLink(rtl::OUString const & rLinkName)
1082     throw (css::registry::InvalidRegistryException, css::uno::RuntimeException)
1083 {
1084     osl::MutexGuard guard(registry_->mutex_);
1085     RegError err = key_.deleteLink(rLinkName);
1086     if (err != REG_NO_ERROR) {
1087         throw css::registry::InvalidRegistryException(
1088             (rtl::OUString(
1089                 RTL_CONSTASCII_USTRINGPARAM(
1090                     "com.sun.star.registry.SimpleRegistry key deleteLink:"
1091                     " underlying RegistryKey::deleteLink() = ")) +
1092              rtl::OUString::valueOf(static_cast< sal_Int32 >(err))),
1093             static_cast< OWeakObject * >(this));
1094     }
1095 }
1096 
1097 rtl::OUString Key::getLinkTarget(rtl::OUString const & rLinkName)
1098     throw (css::registry::InvalidRegistryException, css::uno::RuntimeException)
1099 {
1100     osl::MutexGuard guard(registry_->mutex_);
1101     rtl::OUString target;
1102     RegError err = key_.getLinkTarget(rLinkName, target);
1103     if (err != REG_NO_ERROR) {
1104         throw css::registry::InvalidRegistryException(
1105             (rtl::OUString(
1106                 RTL_CONSTASCII_USTRINGPARAM(
1107                     "com.sun.star.registry.SimpleRegistry key getLinkTarget:"
1108                     " underlying RegistryKey::getLinkTarget() = ")) +
1109              rtl::OUString::valueOf(static_cast< sal_Int32 >(err))),
1110             static_cast< OWeakObject * >(this));
1111     }
1112     return target;
1113 }
1114 
1115 rtl::OUString Key::getResolvedName(rtl::OUString const & aKeyName)
1116     throw (css::registry::InvalidRegistryException, css::uno::RuntimeException)
1117 {
1118     osl::MutexGuard guard(registry_->mutex_);
1119     rtl::OUString resolved;
1120     RegError err = key_.getResolvedKeyName(aKeyName, true, resolved);
1121     if (err != REG_NO_ERROR) {
1122         throw css::registry::InvalidRegistryException(
1123             (rtl::OUString(
1124                 RTL_CONSTASCII_USTRINGPARAM(
1125                     "com.sun.star.registry.SimpleRegistry key getResolvedName:"
1126                     " underlying RegistryKey::getResolvedName() = ")) +
1127              rtl::OUString::valueOf(static_cast< sal_Int32 >(err))),
1128             static_cast< OWeakObject * >(this));
1129     }
1130     return resolved;
1131 }
1132 
1133 rtl::OUString SimpleRegistry::getURL() throw (css::uno::RuntimeException) {
1134     osl::MutexGuard guard(mutex_);
1135     return textual_.get() == 0 ? registry_.getName() : textual_->getUri();
1136 }
1137 
1138 void SimpleRegistry::open(
1139     rtl::OUString const & rURL, sal_Bool bReadOnly, sal_Bool bCreate)
1140     throw (css::registry::InvalidRegistryException, css::uno::RuntimeException)
1141 {
1142     osl::MutexGuard guard(mutex_);
1143     if (textual_.get() != 0) {
1144         throw css::registry::InvalidRegistryException(
1145             (rtl::OUString(
1146                 RTL_CONSTASCII_USTRINGPARAM(
1147                     "com.sun.star.registry.SimpleRegistry.open(")) +
1148              rURL +
1149              rtl::OUString(
1150                 RTL_CONSTASCII_USTRINGPARAM(
1151                     "): instance already open"))),
1152             static_cast< OWeakObject * >(this));
1153     }
1154     RegError err = (rURL.getLength() == 0 && bCreate)
1155         ? REG_REGISTRY_NOT_EXISTS
1156         : registry_.open(rURL, bReadOnly ? REG_READONLY : REG_READWRITE);
1157     if (err == REG_REGISTRY_NOT_EXISTS && bCreate) {
1158         err = registry_.create(rURL);
1159     }
1160     switch (err) {
1161     case REG_NO_ERROR:
1162         break;
1163     case REG_INVALID_REGISTRY:
1164         if (bReadOnly && !bCreate) {
1165             textual_.reset(new stoc::simpleregistry::TextualServices(rURL));
1166             break;
1167         }
1168         // fall through
1169     default:
1170         throw css::registry::InvalidRegistryException(
1171             (rtl::OUString(
1172                 RTL_CONSTASCII_USTRINGPARAM(
1173                     "com.sun.star.registry.SimpleRegistry.open(")) +
1174              rURL +
1175              rtl::OUString(
1176                 RTL_CONSTASCII_USTRINGPARAM(
1177                     "): underlying Registry::open/create() = ")) +
1178              rtl::OUString::valueOf(static_cast< sal_Int32 >(err))),
1179             static_cast< OWeakObject * >(this));
1180     }
1181 }
1182 
1183 sal_Bool SimpleRegistry::isValid() throw (css::uno::RuntimeException) {
1184     osl::MutexGuard guard(mutex_);
1185     return textual_.get() != 0 || registry_.isValid();
1186 }
1187 
1188 void SimpleRegistry::close()
1189     throw (css::registry::InvalidRegistryException, css::uno::RuntimeException)
1190 {
1191     osl::MutexGuard guard(mutex_);
1192     if (textual_.get() != 0) {
1193         textual_.reset();
1194         return;
1195     }
1196     RegError err = registry_.close();
1197     if (err != REG_NO_ERROR) {
1198         throw css::registry::InvalidRegistryException(
1199             (rtl::OUString(
1200                 RTL_CONSTASCII_USTRINGPARAM(
1201                     "com.sun.star.registry.SimpleRegistry.close:"
1202                     " underlying Registry::close() = ")) +
1203              rtl::OUString::valueOf(static_cast< sal_Int32 >(err))),
1204             static_cast< OWeakObject * >(this));
1205     }
1206 }
1207 
1208 void SimpleRegistry::destroy()
1209     throw (css::registry::InvalidRegistryException, css::uno::RuntimeException)
1210 {
1211     osl::MutexGuard guard(mutex_);
1212     if (textual_.get() != 0) {
1213         textual_.reset();
1214         return;
1215     }
1216     RegError err = registry_.destroy(rtl::OUString());
1217     if (err != REG_NO_ERROR) {
1218         throw css::registry::InvalidRegistryException(
1219             (rtl::OUString(
1220                 RTL_CONSTASCII_USTRINGPARAM(
1221                     "com.sun.star.registry.SimpleRegistry.destroy:"
1222                     " underlying Registry::destroy() = ")) +
1223              rtl::OUString::valueOf(static_cast< sal_Int32 >(err))),
1224             static_cast< OWeakObject * >(this));
1225     }
1226 }
1227 
1228 css::uno::Reference< css::registry::XRegistryKey > SimpleRegistry::getRootKey()
1229     throw (css::registry::InvalidRegistryException, css::uno::RuntimeException)
1230 {
1231     osl::MutexGuard guard(mutex_);
1232     if (textual_.get() != 0) {
1233         return textual_->getRootKey();
1234     }
1235     RegistryKey root;
1236     RegError err = registry_.openRootKey(root);
1237     if (err != REG_NO_ERROR) {
1238         throw css::registry::InvalidRegistryException(
1239             (rtl::OUString(
1240                 RTL_CONSTASCII_USTRINGPARAM(
1241                     "com.sun.star.registry.SimpleRegistry.getRootKey:"
1242                     " underlying Registry::getRootKey() = ")) +
1243              rtl::OUString::valueOf(static_cast< sal_Int32 >(err))),
1244             static_cast< OWeakObject * >(this));
1245     }
1246     return new Key(this, root);
1247 }
1248 
1249 sal_Bool SimpleRegistry::isReadOnly()
1250     throw (css::registry::InvalidRegistryException, css::uno::RuntimeException)
1251 {
1252     osl::MutexGuard guard(mutex_);
1253     return textual_.get() != 0 || registry_.isReadOnly();
1254 }
1255 
1256 void SimpleRegistry::mergeKey(
1257     rtl::OUString const & aKeyName, rtl::OUString const & aUrl)
1258     throw (
1259         css::registry::InvalidRegistryException,
1260         css::registry::MergeConflictException, css::uno::RuntimeException)
1261 {
1262     osl::MutexGuard guard(mutex_);
1263     if (textual_.get() != 0) {
1264         throw css::uno::RuntimeException(
1265             rtl::OUString(
1266                 RTL_CONSTASCII_USTRINGPARAM(
1267                     "com.sun.star.registry.SimpleRegistry.mergeKey: not"
1268                     " supported for textual representation")),
1269             static_cast< cppu::OWeakObject * >(this));
1270     }
1271     RegistryKey root;
1272     RegError err = registry_.openRootKey(root);
1273     if (err == REG_NO_ERROR) {
1274         err = registry_.mergeKey(root, aKeyName, aUrl, false, false);
1275     }
1276     switch (err) {
1277     case REG_NO_ERROR:
1278     case REG_MERGE_CONFLICT:
1279         break;
1280     case REG_MERGE_ERROR:
1281         throw css::registry::MergeConflictException(
1282             rtl::OUString(
1283                 RTL_CONSTASCII_USTRINGPARAM(
1284                     "com.sun.star.registry.SimpleRegistry.mergeKey:"
1285                     " underlying Registry::mergeKey() = REG_MERGE_ERROR")),
1286             static_cast< cppu::OWeakObject * >(this));
1287     default:
1288         throw css::registry::InvalidRegistryException(
1289             (rtl::OUString(
1290                 RTL_CONSTASCII_USTRINGPARAM(
1291                     "com.sun.star.registry.SimpleRegistry.mergeKey:"
1292                     " underlying Registry::getRootKey/mergeKey() = ")) +
1293              rtl::OUString::valueOf(static_cast< sal_Int32 >(err))),
1294             static_cast< OWeakObject * >(this));
1295     }
1296 }
1297 
1298 }
1299 
1300 namespace stoc_bootstrap {
1301 
1302 css::uno::Reference< css::uno::XInterface > SimpleRegistry_CreateInstance(
1303     css::uno::Reference< css::uno::XComponentContext > const &)
1304 {
1305     return static_cast< cppu::OWeakObject * >(new SimpleRegistry);
1306 }
1307 
1308 css::uno::Sequence< rtl::OUString > simreg_getSupportedServiceNames() {
1309     css::uno::Sequence< rtl::OUString > names(1);
1310     names[0] = rtl::OUString(
1311         RTL_CONSTASCII_USTRINGPARAM("com.sun.star.registry.SimpleRegistry"));
1312     return names;
1313 }
1314 
1315 rtl::OUString simreg_getImplementationName() {
1316     return rtl::OUString(
1317         RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.stoc.SimpleRegistry"));
1318 }
1319 
1320 }
1321