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