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