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 <string.h>
22 :
23 : #include "keyimpl.hxx"
24 :
25 : #include "reflcnst.hxx"
26 : #include "rtl/alloc.h"
27 : #include "rtl/ustrbuf.hxx"
28 : #include <osl/diagnose.h>
29 : #include <sal/log.hxx>
30 :
31 : using namespace store;
32 :
33 : namespace { static char const VALUE_PREFIX[] = "$VL_"; }
34 :
35 :
36 : // ORegKey()
37 :
38 577 : ORegKey::ORegKey(const OUString& keyName, ORegistry* pReg)
39 : : m_refCount(1)
40 : , m_name(keyName)
41 : , m_bDeleted(false)
42 : , m_bModified(false)
43 577 : , m_pRegistry(pReg)
44 : {
45 577 : }
46 :
47 :
48 : // ~ORegKey()
49 :
50 570 : ORegKey::~ORegKey()
51 : {
52 : SAL_WARN_IF(m_refCount != 0, "registry", "registry::ORegKey::dtor(): refcount not zero.");
53 570 : }
54 :
55 :
56 : // releaseKey
57 :
58 0 : RegError ORegKey::releaseKey(RegKeyHandle hKey)
59 : {
60 0 : return m_pRegistry->releaseKey(hKey);
61 : }
62 :
63 :
64 : // createKey
65 :
66 408 : RegError ORegKey::createKey(const OUString& keyName, RegKeyHandle* phNewKey)
67 : {
68 408 : return m_pRegistry->createKey(this, keyName, phNewKey);
69 : }
70 :
71 :
72 :
73 : // openKey
74 :
75 34 : RegError ORegKey::openKey(const OUString& keyName, RegKeyHandle* phOpenKey)
76 : {
77 34 : return m_pRegistry->openKey(this, keyName, phOpenKey);
78 : }
79 :
80 :
81 :
82 : // openSubKeys
83 :
84 7 : RegError ORegKey::openSubKeys(const OUString& keyName, RegKeyHandle** phOpenSubKeys, sal_uInt32* pnSubKeys)
85 : {
86 7 : RegError _ret = RegError::NO_ERROR;
87 :
88 7 : *phOpenSubKeys = 0;
89 7 : *pnSubKeys = 0;
90 :
91 7 : ORegKey* pKey = this;
92 7 : if ( !keyName.isEmpty() )
93 : {
94 0 : _ret = openKey(keyName, reinterpret_cast<RegKeyHandle*>(&pKey));
95 0 : if (_ret != RegError::NO_ERROR)
96 0 : return _ret;
97 : }
98 :
99 7 : sal_uInt32 nSubKeys = pKey->countSubKeys();
100 7 : *pnSubKeys = nSubKeys;
101 :
102 : ORegKey** pSubKeys;
103 7 : pSubKeys = static_cast<ORegKey**>(rtl_allocateZeroMemory(nSubKeys * sizeof(ORegKey*)));
104 :
105 : OStoreDirectory::iterator iter;
106 7 : OStoreDirectory rStoreDir(pKey->getStoreDir());
107 7 : storeError _err = rStoreDir.first(iter);
108 :
109 7 : nSubKeys = 0;
110 22 : while ( _err == store_E_None )
111 : {
112 8 : if ( iter.m_nAttrib & STORE_ATTRIB_ISDIR )
113 : {
114 8 : OUString const sSubKeyName = iter.m_pszName;
115 :
116 8 : ORegKey* pOpenSubKey = 0;
117 8 : _ret = pKey->openKey(sSubKeyName, reinterpret_cast<RegKeyHandle*>(&pOpenSubKey));
118 8 : if (_ret != RegError::NO_ERROR)
119 : {
120 0 : *phOpenSubKeys = NULL;
121 0 : *pnSubKeys = 0;
122 0 : rtl_freeMemory(pSubKeys); // @@@ leaking 'pSubKeys[0...nSubkeys-1]'
123 0 : return _ret; // @@@ leaking 'pKey'
124 : }
125 :
126 8 : pSubKeys[nSubKeys] = pOpenSubKey;
127 :
128 8 : nSubKeys++;
129 : }
130 :
131 8 : _err = rStoreDir.next(iter);
132 : }
133 :
134 7 : *phOpenSubKeys = reinterpret_cast<RegKeyHandle*>(pSubKeys);
135 7 : if (!keyName.isEmpty())
136 : {
137 0 : (void) releaseKey(pKey);
138 : }
139 7 : return RegError::NO_ERROR;
140 : }
141 :
142 :
143 :
144 : // getKeyNames
145 :
146 8 : RegError ORegKey::getKeyNames(const OUString& keyName,
147 : rtl_uString*** pSubKeyNames,
148 : sal_uInt32* pnSubKeys)
149 : {
150 8 : RegError _ret = RegError::NO_ERROR;
151 :
152 8 : *pSubKeyNames = 0;
153 8 : *pnSubKeys = 0;
154 :
155 8 : ORegKey* pKey = this;
156 8 : if (!keyName.isEmpty())
157 : {
158 0 : _ret = openKey(keyName, reinterpret_cast<RegKeyHandle*>(&pKey));
159 0 : if (_ret != RegError::NO_ERROR)
160 0 : return _ret;
161 : }
162 :
163 8 : sal_uInt32 nSubKeys = pKey->countSubKeys();
164 8 : *pnSubKeys = nSubKeys;
165 :
166 8 : rtl_uString** pSubKeys = 0;
167 8 : pSubKeys = static_cast<rtl_uString**>(rtl_allocateZeroMemory(nSubKeys * sizeof(rtl_uString*)));
168 :
169 : OStoreDirectory::iterator iter;
170 8 : OStoreDirectory rStoreDir(pKey->getStoreDir());
171 8 : storeError _err = rStoreDir.first(iter);
172 :
173 8 : nSubKeys = 0;
174 :
175 25 : while ( _err == store_E_None )
176 : {
177 9 : if ( iter.m_nAttrib & STORE_ATTRIB_ISDIR)
178 : {
179 7 : OUString const sSubKeyName = iter.m_pszName;
180 :
181 14 : OUString sFullKeyName(pKey->getName());
182 7 : if (sFullKeyName.getLength() > 1)
183 6 : sFullKeyName += m_pRegistry->ROOT;
184 7 : sFullKeyName += sSubKeyName;
185 :
186 7 : rtl_uString_newFromString(&pSubKeys[nSubKeys], sFullKeyName.pData);
187 :
188 14 : nSubKeys++;
189 : }
190 :
191 9 : _err = rStoreDir.next(iter);
192 : }
193 :
194 8 : *pSubKeyNames = pSubKeys;
195 8 : if (!keyName.isEmpty())
196 : {
197 0 : releaseKey(pKey);
198 : }
199 8 : return RegError::NO_ERROR;
200 : }
201 :
202 :
203 :
204 : // closeKey
205 :
206 27 : RegError ORegKey::closeKey(RegKeyHandle hKey)
207 : {
208 27 : return (m_pRegistry->closeKey(hKey));
209 : }
210 :
211 :
212 :
213 : // deleteKey
214 :
215 2 : RegError ORegKey::deleteKey(const OUString& keyName)
216 : {
217 2 : return (m_pRegistry->deleteKey(this, keyName));
218 : }
219 :
220 :
221 :
222 : // getValueType
223 :
224 14 : RegError ORegKey::getValueInfo(const OUString& valueName, RegValueType* pValueType, sal_uInt32* pValueSize) const
225 : {
226 14 : OStoreStream rValue;
227 : sal_uInt8* pBuffer;
228 14 : storeAccessMode accessMode = VALUE_MODE_OPEN;
229 :
230 14 : if (m_pRegistry->isReadOnly())
231 : {
232 0 : accessMode = VALUE_MODE_OPENREAD;
233 : }
234 :
235 28 : OUString sImplValueName( VALUE_PREFIX );
236 14 : sImplValueName += valueName;
237 :
238 28 : REG_GUARD(m_pRegistry->m_mutex);
239 :
240 14 : if ( rValue.create(m_pRegistry->getStoreFile(), m_name + m_pRegistry->ROOT, sImplValueName, accessMode) )
241 : {
242 8 : *pValueType = RegValueType::NOT_DEFINED;
243 8 : *pValueSize = 0;
244 8 : return RegError::VALUE_NOT_EXISTS;
245 : }
246 :
247 6 : pBuffer = static_cast<sal_uInt8*>(rtl_allocateMemory(VALUE_HEADERSIZE));
248 :
249 : sal_uInt32 readBytes;
250 6 : if ( rValue.readAt(0, pBuffer, VALUE_HEADERSIZE, readBytes) )
251 : {
252 0 : rtl_freeMemory(pBuffer);
253 0 : return RegError::INVALID_VALUE;
254 : }
255 6 : if (readBytes != VALUE_HEADERSIZE)
256 : {
257 0 : rtl_freeMemory(pBuffer);
258 0 : return RegError::INVALID_VALUE;
259 : }
260 :
261 : sal_uInt32 size;
262 6 : sal_uInt8 type = *pBuffer;
263 6 : readUINT32(pBuffer+VALUE_TYPEOFFSET, size);
264 :
265 6 : *pValueType = (RegValueType)type;
266 : // if (*pValueType == RegValueType::UNICODE)
267 : // {
268 : // *pValueSize = (size / 2) * sizeof(sal_Unicode);
269 : // } else
270 : // {
271 6 : if (*pValueType > RegValueType::BINARY)
272 : {
273 0 : rtl_freeMemory(pBuffer);
274 0 : pBuffer = static_cast<sal_uInt8*>(rtl_allocateMemory(4));
275 0 : rValue.readAt(VALUE_HEADEROFFSET, pBuffer, 4, readBytes);
276 :
277 0 : readUINT32(pBuffer, size);
278 : }
279 :
280 6 : *pValueSize = size;
281 : // }
282 :
283 6 : rtl_freeMemory(pBuffer);
284 20 : return RegError::NO_ERROR;
285 : }
286 :
287 :
288 :
289 : // setValue
290 :
291 397 : RegError ORegKey::setValue(const OUString& valueName, RegValueType vType, RegValue value, sal_uInt32 vSize)
292 : {
293 397 : OStoreStream rValue;
294 : sal_uInt8* pBuffer;
295 :
296 397 : if (m_pRegistry->isReadOnly())
297 : {
298 0 : return RegError::REGISTRY_READONLY;
299 : }
300 :
301 397 : if (vType > RegValueType::BINARY)
302 : {
303 0 : return RegError::INVALID_VALUE;
304 : }
305 :
306 794 : OUString sImplValueName( VALUE_PREFIX );
307 397 : sImplValueName += valueName;
308 :
309 794 : REG_GUARD(m_pRegistry->m_mutex);
310 :
311 397 : if ( rValue.create(getStoreFile(), m_name + m_pRegistry->ROOT , sImplValueName, VALUE_MODE_CREATE) )
312 : {
313 0 : return RegError::SET_VALUE_FAILED;
314 : }
315 :
316 397 : sal_uInt32 size = vSize;
317 :
318 397 : sal_uInt8 type = (sal_uInt8)vType;
319 397 : pBuffer = static_cast<sal_uInt8*>(rtl_allocateMemory(VALUE_HEADERSIZE + size));
320 397 : memcpy(pBuffer, &type, 1);
321 :
322 397 : writeUINT32(pBuffer+VALUE_TYPEOFFSET, size);
323 :
324 397 : switch (vType)
325 : {
326 : case RegValueType::NOT_DEFINED:
327 0 : memcpy(pBuffer+VALUE_HEADEROFFSET, value, size);
328 0 : break;
329 : case RegValueType::LONG:
330 0 : writeINT32(pBuffer+VALUE_HEADEROFFSET, *static_cast<sal_Int32*>(value));
331 0 : break;
332 : case RegValueType::STRING:
333 4 : writeUtf8(pBuffer+VALUE_HEADEROFFSET, static_cast<const sal_Char*>(value));
334 4 : break;
335 : case RegValueType::UNICODE:
336 0 : writeString(pBuffer+VALUE_HEADEROFFSET, static_cast<const sal_Unicode*>(value));
337 0 : break;
338 : case RegValueType::BINARY:
339 393 : memcpy(pBuffer+VALUE_HEADEROFFSET, value, size);
340 393 : break;
341 : default:
342 : OSL_ASSERT(false);
343 0 : break;
344 : }
345 :
346 : sal_uInt32 writenBytes;
347 397 : if ( rValue.writeAt(0, pBuffer, VALUE_HEADERSIZE+size, writenBytes) )
348 : {
349 0 : rtl_freeMemory(pBuffer);
350 0 : return RegError::SET_VALUE_FAILED;
351 : }
352 397 : if (writenBytes != (VALUE_HEADERSIZE+size))
353 : {
354 0 : rtl_freeMemory(pBuffer);
355 0 : return RegError::SET_VALUE_FAILED;
356 : }
357 397 : setModified();
358 :
359 397 : rtl_freeMemory(pBuffer);
360 794 : return RegError::NO_ERROR;
361 : }
362 :
363 :
364 : // setLongListValue
365 :
366 0 : RegError ORegKey::setLongListValue(const OUString& valueName, sal_Int32* pValueList, sal_uInt32 len)
367 : {
368 0 : OStoreStream rValue;
369 : sal_uInt8* pBuffer;
370 :
371 0 : if (m_pRegistry->isReadOnly())
372 : {
373 0 : return RegError::REGISTRY_READONLY;
374 : }
375 :
376 0 : OUString sImplValueName( VALUE_PREFIX );
377 0 : sImplValueName += valueName;
378 :
379 0 : REG_GUARD(m_pRegistry->m_mutex);
380 :
381 0 : if (rValue.create(getStoreFile(), m_name + m_pRegistry->ROOT, sImplValueName, VALUE_MODE_CREATE) )
382 : {
383 0 : return RegError::SET_VALUE_FAILED;
384 : }
385 :
386 0 : sal_uInt32 size = 4; // 4 bytes (sal_uInt32) for the length
387 :
388 0 : size += len * 4;
389 :
390 0 : sal_uInt8 type = (sal_uInt8)RegValueType::LONGLIST;
391 0 : pBuffer = static_cast<sal_uInt8*>(rtl_allocateMemory(VALUE_HEADERSIZE + size));
392 0 : memcpy(pBuffer, &type, 1);
393 :
394 0 : writeUINT32(pBuffer+VALUE_TYPEOFFSET, size);
395 0 : writeUINT32(pBuffer+VALUE_HEADEROFFSET, len);
396 :
397 0 : sal_uInt32 offset = 4; // initial 4 bytes for the size of the array
398 :
399 0 : for (sal_uInt32 i=0; i < len; i++)
400 : {
401 0 : writeINT32(pBuffer+VALUE_HEADEROFFSET+offset, pValueList[i]);
402 0 : offset += 4;
403 : }
404 :
405 : sal_uInt32 writenBytes;
406 0 : if ( rValue.writeAt(0, pBuffer, VALUE_HEADERSIZE+size, writenBytes) )
407 : {
408 0 : rtl_freeMemory(pBuffer);
409 0 : return RegError::SET_VALUE_FAILED;
410 : }
411 0 : if (writenBytes != (VALUE_HEADEROFFSET+size))
412 : {
413 0 : rtl_freeMemory(pBuffer);
414 0 : return RegError::SET_VALUE_FAILED;
415 : }
416 0 : setModified();
417 :
418 0 : rtl_freeMemory(pBuffer);
419 0 : return RegError::NO_ERROR;
420 : }
421 :
422 :
423 : // setStringListValue
424 :
425 1 : RegError ORegKey::setStringListValue(const OUString& valueName, sal_Char** pValueList, sal_uInt32 len)
426 : {
427 1 : OStoreStream rValue;
428 : sal_uInt8* pBuffer;
429 :
430 1 : if (m_pRegistry->isReadOnly())
431 : {
432 0 : return RegError::REGISTRY_READONLY;
433 : }
434 :
435 2 : OUString sImplValueName( VALUE_PREFIX );
436 1 : sImplValueName += valueName;
437 :
438 2 : REG_GUARD(m_pRegistry->m_mutex);
439 :
440 1 : if (rValue.create(getStoreFile(), m_name + m_pRegistry->ROOT, sImplValueName, VALUE_MODE_CREATE) )
441 : {
442 0 : return RegError::SET_VALUE_FAILED;
443 : }
444 :
445 1 : sal_uInt32 size = 4; // 4 bytes (sal_uInt32) for the length
446 :
447 : sal_uInt32 i;
448 2 : for (i=0; i < len; i++)
449 : {
450 1 : size += 4 + strlen(pValueList[i]) + 1;
451 : }
452 :
453 1 : sal_uInt8 type = (sal_uInt8)RegValueType::STRINGLIST;
454 1 : pBuffer = static_cast<sal_uInt8*>(rtl_allocateMemory(VALUE_HEADERSIZE + size));
455 1 : memcpy(pBuffer, &type, 1);
456 :
457 1 : writeUINT32(pBuffer+VALUE_TYPEOFFSET, size);
458 1 : writeUINT32(pBuffer+VALUE_HEADEROFFSET, len);
459 :
460 1 : sal_uInt32 offset = 4; // initial 4 bytes for the size of the array;
461 1 : sal_uInt32 sLen = 0;
462 :
463 2 : for (i=0; i < len; i++)
464 : {
465 1 : sLen = strlen(pValueList[i]) + 1;
466 1 : writeUINT32(pBuffer+VALUE_HEADEROFFSET+offset, sLen);
467 :
468 1 : offset += 4;
469 1 : writeUtf8(pBuffer+VALUE_HEADEROFFSET+offset, pValueList[i]);
470 1 : offset += sLen;
471 : }
472 :
473 : sal_uInt32 writenBytes;
474 1 : if ( rValue.writeAt(0, pBuffer, VALUE_HEADERSIZE+size, writenBytes) )
475 : {
476 0 : rtl_freeMemory(pBuffer);
477 0 : return RegError::SET_VALUE_FAILED;
478 : }
479 1 : if (writenBytes != (VALUE_HEADERSIZE+size))
480 : {
481 0 : rtl_freeMemory(pBuffer);
482 0 : return RegError::SET_VALUE_FAILED;
483 : }
484 1 : setModified();
485 :
486 1 : rtl_freeMemory(pBuffer);
487 2 : return RegError::NO_ERROR;
488 : }
489 :
490 :
491 : // setUnicodeListValue
492 :
493 0 : RegError ORegKey::setUnicodeListValue(const OUString& valueName, sal_Unicode** pValueList, sal_uInt32 len)
494 : {
495 0 : OStoreStream rValue;
496 : sal_uInt8* pBuffer;
497 :
498 0 : if (m_pRegistry->isReadOnly())
499 : {
500 0 : return RegError::REGISTRY_READONLY;
501 : }
502 :
503 0 : OUString sImplValueName( VALUE_PREFIX );
504 0 : sImplValueName += valueName;
505 :
506 0 : REG_GUARD(m_pRegistry->m_mutex);
507 :
508 0 : if (rValue.create(getStoreFile(), m_name + m_pRegistry->ROOT, sImplValueName, VALUE_MODE_CREATE) )
509 : {
510 0 : return RegError::SET_VALUE_FAILED;
511 : }
512 :
513 0 : sal_uInt32 size = 4; // 4 bytes (sal_uInt32) for the length
514 :
515 : sal_uInt32 i;
516 0 : for (i=0; i < len; i++)
517 : {
518 0 : size += 4 + ((rtl_ustr_getLength(pValueList[i]) +1) * 2);
519 : }
520 :
521 0 : sal_uInt8 type = (sal_uInt8)RegValueType::UNICODELIST;
522 0 : pBuffer = static_cast<sal_uInt8*>(rtl_allocateMemory(VALUE_HEADERSIZE + size));
523 0 : memcpy(pBuffer, &type, 1);
524 :
525 0 : writeUINT32(pBuffer+VALUE_TYPEOFFSET, size);
526 0 : writeUINT32(pBuffer+VALUE_HEADEROFFSET, len);
527 :
528 0 : sal_uInt32 offset = 4; // initial 4 bytes for the size of the array;
529 0 : sal_uInt32 sLen = 0;
530 :
531 0 : for (i=0; i < len; i++)
532 : {
533 0 : sLen = (rtl_ustr_getLength(pValueList[i]) + 1) * 2;
534 0 : writeUINT32(pBuffer+VALUE_HEADEROFFSET+offset, sLen);
535 :
536 0 : offset += 4;
537 0 : writeString(pBuffer+VALUE_HEADEROFFSET+offset, pValueList[i]);
538 0 : offset += sLen;
539 : }
540 :
541 : sal_uInt32 writenBytes;
542 0 : if ( rValue.writeAt(0, pBuffer, VALUE_HEADERSIZE+size, writenBytes) )
543 : {
544 0 : rtl_freeMemory(pBuffer);
545 0 : return RegError::SET_VALUE_FAILED;
546 : }
547 0 : if (writenBytes != (VALUE_HEADERSIZE+size))
548 : {
549 0 : rtl_freeMemory(pBuffer);
550 0 : return RegError::SET_VALUE_FAILED;
551 : }
552 0 : setModified();
553 :
554 0 : rtl_freeMemory(pBuffer);
555 0 : return RegError::NO_ERROR;
556 : }
557 :
558 :
559 : // getValue
560 :
561 3 : RegError ORegKey::getValue(const OUString& valueName, RegValue value) const
562 : {
563 3 : OStoreStream rValue;
564 : sal_uInt8* pBuffer;
565 : RegValueType valueType;
566 : sal_uInt32 valueSize;
567 3 : storeAccessMode accessMode = VALUE_MODE_OPEN;
568 :
569 3 : if (m_pRegistry->isReadOnly())
570 : {
571 0 : accessMode = VALUE_MODE_OPENREAD;
572 : }
573 :
574 6 : OUString sImplValueName( VALUE_PREFIX );
575 3 : sImplValueName += valueName;
576 :
577 6 : REG_GUARD(m_pRegistry->m_mutex);
578 :
579 3 : if (rValue.create(getStoreFile(), m_name + m_pRegistry->ROOT, sImplValueName, accessMode) )
580 : {
581 0 : return RegError::VALUE_NOT_EXISTS;
582 : }
583 :
584 3 : pBuffer = static_cast<sal_uInt8*>(rtl_allocateMemory(VALUE_HEADERSIZE));
585 :
586 : sal_uInt32 readBytes;
587 3 : if ( rValue.readAt(0, pBuffer, VALUE_HEADERSIZE, readBytes) )
588 : {
589 0 : rtl_freeMemory(pBuffer);
590 0 : return RegError::INVALID_VALUE;
591 : }
592 3 : if (readBytes != VALUE_HEADERSIZE)
593 : {
594 0 : rtl_freeMemory(pBuffer);
595 0 : return RegError::INVALID_VALUE;
596 : }
597 :
598 3 : sal_uInt8 type = *pBuffer;
599 3 : valueType = (RegValueType)type;
600 3 : readUINT32(pBuffer+VALUE_TYPEOFFSET, valueSize);
601 :
602 3 : rtl_freeMemory(pBuffer);
603 :
604 3 : if (valueType > RegValueType::BINARY)
605 : {
606 0 : return RegError::INVALID_VALUE;
607 : }
608 :
609 3 : pBuffer = static_cast<sal_uInt8*>(rtl_allocateMemory(valueSize));
610 :
611 3 : if ( rValue.readAt(VALUE_HEADEROFFSET, pBuffer, valueSize, readBytes) )
612 : {
613 0 : rtl_freeMemory(pBuffer);
614 0 : return RegError::INVALID_VALUE;
615 : }
616 3 : if (readBytes != valueSize)
617 : {
618 0 : rtl_freeMemory(pBuffer);
619 0 : return RegError::INVALID_VALUE;
620 : }
621 :
622 3 : switch (valueType)
623 : {
624 : case RegValueType::NOT_DEFINED:
625 0 : memcpy(value, pBuffer, valueSize);
626 0 : break;
627 : case RegValueType::LONG:
628 0 : readINT32(pBuffer, *static_cast<sal_Int32*>(value));
629 0 : break;
630 : case RegValueType::STRING:
631 3 : readUtf8(pBuffer, static_cast<sal_Char*>(value), valueSize);
632 3 : break;
633 : case RegValueType::UNICODE:
634 0 : readString(pBuffer, static_cast<sal_Unicode*>(value), valueSize);
635 0 : break;
636 : case RegValueType::BINARY:
637 0 : memcpy(value, pBuffer, valueSize);
638 0 : break;
639 : // coverity[dead_error_begin] - following conditions exist to avoid compiler warning
640 : case RegValueType::LONGLIST:
641 : case RegValueType::STRINGLIST:
642 : case RegValueType::UNICODELIST:
643 0 : memcpy(value, pBuffer, valueSize);
644 0 : break;
645 : }
646 :
647 :
648 3 : rtl_freeMemory(pBuffer);
649 6 : return RegError::NO_ERROR;
650 : }
651 :
652 :
653 : // getLongListValue
654 :
655 0 : RegError ORegKey::getLongListValue(const OUString& valueName, sal_Int32** pValueList, sal_uInt32* pLen) const
656 : {
657 0 : OStoreStream rValue;
658 : sal_uInt8* pBuffer;
659 : RegValueType valueType;
660 : sal_uInt32 valueSize;
661 0 : storeAccessMode accessMode = VALUE_MODE_OPEN;
662 :
663 0 : if (m_pRegistry->isReadOnly())
664 : {
665 0 : accessMode = VALUE_MODE_OPENREAD;
666 : }
667 :
668 0 : OUString sImplValueName( VALUE_PREFIX );
669 0 : sImplValueName += valueName;
670 :
671 0 : REG_GUARD(m_pRegistry->m_mutex);
672 :
673 0 : if (rValue.create(getStoreFile(), m_name + m_pRegistry->ROOT, sImplValueName, accessMode) )
674 : {
675 0 : pValueList = NULL;
676 0 : *pLen = 0;
677 0 : return RegError::VALUE_NOT_EXISTS;
678 : }
679 :
680 0 : pBuffer = static_cast<sal_uInt8*>(rtl_allocateMemory(VALUE_HEADERSIZE));
681 :
682 : sal_uInt32 readBytes;
683 0 : if ( rValue.readAt(0, pBuffer, VALUE_HEADERSIZE, readBytes) )
684 : {
685 0 : pValueList = NULL;
686 0 : *pLen = 0;
687 0 : rtl_freeMemory(pBuffer);
688 0 : return RegError::INVALID_VALUE;
689 : }
690 0 : if (readBytes != VALUE_HEADERSIZE)
691 : {
692 0 : pValueList = NULL;
693 0 : *pLen = 0;
694 0 : rtl_freeMemory(pBuffer);
695 0 : return RegError::INVALID_VALUE;
696 : }
697 :
698 0 : sal_uInt8 type = *pBuffer;
699 0 : valueType = (RegValueType)type;
700 :
701 0 : if (valueType != RegValueType::LONGLIST)
702 : {
703 0 : pValueList = NULL;
704 0 : *pLen = 0;
705 0 : rtl_freeMemory(pBuffer);
706 0 : return RegError::INVALID_VALUE;
707 : }
708 :
709 0 : readUINT32(pBuffer+VALUE_TYPEOFFSET, valueSize);
710 :
711 0 : rtl_freeMemory(pBuffer);
712 :
713 : /* check for 'reasonable' value */
714 : /* surely 10 millions entry in a registry list should be enough */
715 0 : if(valueSize > 40000000)
716 : {
717 0 : pValueList = NULL;
718 0 : *pLen = 0;
719 0 : rtl_freeMemory(pBuffer);
720 0 : return RegError::INVALID_VALUE;
721 : }
722 0 : pBuffer = static_cast<sal_uInt8*>(rtl_allocateMemory(valueSize));
723 :
724 0 : if ( rValue.readAt(VALUE_HEADEROFFSET, pBuffer, valueSize, readBytes) )
725 : {
726 0 : pValueList = NULL;
727 0 : *pLen = 0;
728 0 : rtl_freeMemory(pBuffer);
729 0 : return RegError::INVALID_VALUE;
730 : }
731 0 : if (readBytes != valueSize)
732 : {
733 0 : pValueList = NULL;
734 0 : *pLen = 0;
735 0 : rtl_freeMemory(pBuffer);
736 0 : return RegError::INVALID_VALUE;
737 : }
738 :
739 0 : sal_uInt32 len = 0;
740 0 : readUINT32(pBuffer, len);
741 :
742 : /* make sure the declared size of the arry is consistent with the amount of data we have read */
743 0 : if(len > (valueSize - 4) / 4)
744 : {
745 0 : pValueList = NULL;
746 0 : *pLen = 0;
747 0 : rtl_freeMemory(pBuffer);
748 0 : return RegError::INVALID_VALUE;
749 : }
750 0 : *pLen = len;
751 0 : sal_Int32* pVList = static_cast<sal_Int32*>(rtl_allocateZeroMemory(len * sizeof(sal_Int32)));
752 :
753 0 : sal_uInt32 offset = 4; // initial 4 bytes for the size of the array;
754 :
755 0 : for (sal_uInt32 i = 0; i < len; i++)
756 : {
757 0 : readINT32(pBuffer+offset, pVList[i]);
758 0 : offset += 4;
759 : }
760 :
761 0 : *pValueList = pVList;
762 0 : rtl_freeMemory(pBuffer);
763 0 : return RegError::NO_ERROR;
764 : }
765 :
766 :
767 : // getStringListValue
768 :
769 0 : RegError ORegKey::getStringListValue(const OUString& valueName, sal_Char*** pValueList, sal_uInt32* pLen) const
770 : {
771 0 : OStoreStream rValue;
772 : sal_uInt8* pBuffer;
773 : RegValueType valueType;
774 : sal_uInt32 valueSize;
775 0 : storeAccessMode accessMode = VALUE_MODE_OPEN;
776 :
777 0 : if (m_pRegistry->isReadOnly())
778 : {
779 0 : accessMode = VALUE_MODE_OPENREAD;
780 : }
781 :
782 0 : OUString sImplValueName( VALUE_PREFIX );
783 0 : sImplValueName += valueName;
784 :
785 0 : REG_GUARD(m_pRegistry->m_mutex);
786 :
787 0 : if ( rValue.create(getStoreFile(), m_name + m_pRegistry->ROOT, sImplValueName, accessMode) )
788 : {
789 0 : pValueList = NULL;
790 0 : *pLen = 0;
791 0 : return RegError::VALUE_NOT_EXISTS;
792 : }
793 :
794 0 : pBuffer = static_cast<sal_uInt8*>(rtl_allocateMemory(VALUE_HEADERSIZE));
795 :
796 : sal_uInt32 readBytes;
797 0 : if ( rValue.readAt(0, pBuffer, VALUE_HEADERSIZE, readBytes) )
798 : {
799 0 : pValueList = NULL;
800 0 : *pLen = 0;
801 0 : rtl_freeMemory(pBuffer);
802 0 : return RegError::INVALID_VALUE;
803 : }
804 0 : if (readBytes != VALUE_HEADERSIZE)
805 : {
806 0 : pValueList = NULL;
807 0 : *pLen = 0;
808 0 : rtl_freeMemory(pBuffer);
809 0 : return RegError::INVALID_VALUE;
810 : }
811 :
812 0 : sal_uInt8 type = *pBuffer;
813 0 : valueType = (RegValueType)type;
814 :
815 0 : if (valueType != RegValueType::STRINGLIST)
816 : {
817 0 : pValueList = NULL;
818 0 : *pLen = 0;
819 0 : rtl_freeMemory(pBuffer);
820 0 : return RegError::INVALID_VALUE;
821 : }
822 :
823 0 : readUINT32(pBuffer+VALUE_TYPEOFFSET, valueSize);
824 :
825 0 : rtl_freeMemory(pBuffer);
826 :
827 0 : pBuffer = static_cast<sal_uInt8*>(rtl_allocateMemory(valueSize));
828 :
829 0 : if ( rValue.readAt(VALUE_HEADEROFFSET, pBuffer, valueSize, readBytes) )
830 : {
831 0 : pValueList = NULL;
832 0 : *pLen = 0;
833 0 : rtl_freeMemory(pBuffer);
834 0 : return RegError::INVALID_VALUE;
835 : }
836 0 : if (readBytes != valueSize)
837 : {
838 0 : pValueList = NULL;
839 0 : *pLen = 0;
840 0 : rtl_freeMemory(pBuffer);
841 0 : return RegError::INVALID_VALUE;
842 : }
843 :
844 0 : sal_uInt32 len = 0;
845 0 : readUINT32(pBuffer, len);
846 :
847 0 : *pLen = len;
848 0 : sal_Char** pVList = static_cast<sal_Char**>(rtl_allocateZeroMemory(len * sizeof(sal_Char*)));
849 :
850 0 : sal_uInt32 offset = 4; // initial 4 bytes for the size of the array;
851 0 : sal_uInt32 sLen = 0;
852 :
853 : sal_Char *pValue;
854 0 : for (sal_uInt32 i=0; i < len; i++)
855 : {
856 0 : readUINT32(pBuffer+offset, sLen);
857 :
858 0 : offset += 4;
859 :
860 0 : pValue = static_cast<sal_Char*>(rtl_allocateMemory(sLen));
861 0 : readUtf8(pBuffer+offset, pValue, sLen);
862 0 : pVList[i] = pValue;
863 :
864 0 : offset += sLen;
865 : }
866 :
867 0 : *pValueList = pVList;
868 0 : rtl_freeMemory(pBuffer);
869 0 : return RegError::NO_ERROR;
870 : }
871 :
872 :
873 : // getUnicodeListValue
874 :
875 0 : RegError ORegKey::getUnicodeListValue(const OUString& valueName, sal_Unicode*** pValueList, sal_uInt32* pLen) const
876 : {
877 0 : OStoreStream rValue;
878 : sal_uInt8* pBuffer;
879 : RegValueType valueType;
880 : sal_uInt32 valueSize;
881 0 : storeAccessMode accessMode = VALUE_MODE_OPEN;
882 :
883 0 : if (m_pRegistry->isReadOnly())
884 : {
885 0 : accessMode = VALUE_MODE_OPENREAD;
886 : }
887 :
888 0 : OUString sImplValueName( VALUE_PREFIX );
889 0 : sImplValueName += valueName;
890 :
891 0 : REG_GUARD(m_pRegistry->m_mutex);
892 :
893 0 : if ( rValue.create(getStoreFile(), m_name + m_pRegistry->ROOT, sImplValueName, accessMode) )
894 : {
895 0 : pValueList = NULL;
896 0 : *pLen = 0;
897 0 : return RegError::VALUE_NOT_EXISTS;
898 : }
899 :
900 0 : pBuffer = static_cast<sal_uInt8*>(rtl_allocateMemory(VALUE_HEADERSIZE));
901 :
902 : sal_uInt32 readBytes;
903 0 : if ( rValue.readAt(0, pBuffer, VALUE_HEADERSIZE, readBytes) )
904 : {
905 0 : pValueList = NULL;
906 0 : *pLen = 0;
907 0 : rtl_freeMemory(pBuffer);
908 0 : return RegError::INVALID_VALUE;
909 : }
910 0 : if (readBytes != VALUE_HEADERSIZE)
911 : {
912 0 : pValueList = NULL;
913 0 : *pLen = 0;
914 0 : rtl_freeMemory(pBuffer);
915 0 : return RegError::INVALID_VALUE;
916 : }
917 :
918 0 : sal_uInt8 type = *pBuffer;
919 0 : valueType = (RegValueType)type;
920 :
921 0 : if (valueType != RegValueType::UNICODELIST)
922 : {
923 0 : pValueList = NULL;
924 0 : *pLen = 0;
925 0 : rtl_freeMemory(pBuffer);
926 0 : return RegError::INVALID_VALUE;
927 : }
928 :
929 0 : readUINT32(pBuffer+VALUE_TYPEOFFSET, valueSize);
930 :
931 0 : rtl_freeMemory(pBuffer);
932 :
933 0 : pBuffer = static_cast<sal_uInt8*>(rtl_allocateMemory(valueSize));
934 :
935 0 : if ( rValue.readAt(VALUE_HEADEROFFSET, pBuffer, valueSize, readBytes) )
936 : {
937 0 : pValueList = NULL;
938 0 : *pLen = 0;
939 0 : rtl_freeMemory(pBuffer);
940 0 : return RegError::INVALID_VALUE;
941 : }
942 0 : if (readBytes != valueSize)
943 : {
944 0 : pValueList = NULL;
945 0 : *pLen = 0;
946 0 : rtl_freeMemory(pBuffer);
947 0 : return RegError::INVALID_VALUE;
948 : }
949 :
950 0 : sal_uInt32 len = 0;
951 0 : readUINT32(pBuffer, len);
952 :
953 0 : *pLen = len;
954 0 : sal_Unicode** pVList = static_cast<sal_Unicode**>(rtl_allocateZeroMemory(len * sizeof(sal_Unicode*)));
955 :
956 0 : sal_uInt32 offset = 4; // initial 4 bytes for the size of the array;
957 0 : sal_uInt32 sLen = 0;
958 :
959 : sal_Unicode *pValue;
960 0 : for (sal_uInt32 i=0; i < len; i++)
961 : {
962 0 : readUINT32(pBuffer+offset, sLen);
963 :
964 0 : offset += 4;
965 :
966 0 : pValue = static_cast<sal_Unicode*>(rtl_allocateMemory((sLen / 2) * sizeof(sal_Unicode)));
967 0 : readString(pBuffer+offset, pValue, sLen);
968 0 : pVList[i] = pValue;
969 :
970 0 : offset += sLen;
971 : }
972 :
973 0 : *pValueList = pVList;
974 0 : rtl_freeMemory(pBuffer);
975 0 : return RegError::NO_ERROR;
976 : }
977 :
978 :
979 0 : RegError ORegKey::getResolvedKeyName(const OUString& keyName,
980 : OUString& resolvedName)
981 : {
982 0 : if (keyName.isEmpty())
983 0 : return RegError::INVALID_KEYNAME;
984 :
985 0 : resolvedName = getFullPath(keyName);
986 0 : return RegError::NO_ERROR;
987 : }
988 :
989 :
990 : // countSubKeys()
991 :
992 15 : sal_uInt32 ORegKey::countSubKeys()
993 : {
994 15 : REG_GUARD(m_pRegistry->m_mutex);
995 :
996 : OStoreDirectory::iterator iter;
997 30 : OStoreDirectory rStoreDir = getStoreDir();
998 15 : storeError _err = rStoreDir.first(iter);
999 15 : sal_uInt32 count = 0;
1000 :
1001 47 : while ( _err == store_E_None )
1002 : {
1003 17 : if ( iter.m_nAttrib & STORE_ATTRIB_ISDIR )
1004 : {
1005 15 : count++;
1006 : }
1007 :
1008 17 : _err = rStoreDir.next(iter);
1009 : }
1010 :
1011 30 : return count;
1012 : }
1013 :
1014 37 : OStoreDirectory ORegKey::getStoreDir()
1015 : {
1016 37 : OStoreDirectory rStoreDir;
1017 74 : OUString fullPath;
1018 74 : OUString relativName;
1019 37 : storeAccessMode accessMode = KEY_MODE_OPEN;
1020 :
1021 37 : if ( m_name.equals(m_pRegistry->ROOT) )
1022 : {
1023 4 : fullPath.clear();
1024 4 : relativName.clear();
1025 : } else
1026 : {
1027 33 : fullPath = m_name.copy(0, m_name.lastIndexOf('/') + 1);
1028 33 : relativName = m_name.copy(m_name.lastIndexOf('/') + 1);
1029 : }
1030 :
1031 37 : if (m_pRegistry->isReadOnly())
1032 : {
1033 0 : accessMode = KEY_MODE_OPENREAD;
1034 : }
1035 :
1036 37 : rStoreDir.create(getStoreFile(), fullPath, relativName, accessMode);
1037 :
1038 74 : return rStoreDir;
1039 : }
1040 :
1041 444 : OUString ORegKey::getFullPath(OUString const & path) const {
1042 : OSL_ASSERT(!m_name.isEmpty() && !path.isEmpty());
1043 444 : OUStringBuffer b(m_name);
1044 444 : if (!b.isEmpty() && b[b.getLength() - 1] == '/') {
1045 407 : if (path[0] == '/') {
1046 403 : b.append(path.getStr() + 1, path.getLength() - 1);
1047 : } else {
1048 4 : b.append(path);
1049 : }
1050 : } else {
1051 37 : if (path[0] != '/') {
1052 28 : b.append('/');
1053 : }
1054 37 : b.append(path);
1055 : }
1056 444 : return b.makeStringAndClear();
1057 : }
1058 :
1059 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|