Remove a memory leak
[platform/framework/native/appfw.git] / src / io / FIo_RegistryCore.cpp
1 //
2 // Open Service Platform
3 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
4 //
5 // Licensed under the Apache License, Version 2.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //     http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17
18 /**
19  * @file        FIo_RegistryCore.cpp
20  * @brief       This is the implementation file for _RegistryCore class.
21  */
22
23 #include <unistd.h>
24 #include <new>
25 #include <unique_ptr.h>
26
27 #include <FBaseInteger.h>
28 #include <FBaseDouble.h>
29 #include <FBaseFloat.h>
30 #include <FBaseUuId.h>
31 #include <FBaseByteBuffer.h>
32 #include <FBaseColIEnumerator.h>
33 #include <FBaseUtilStringTokenizer.h>
34 #include <FBaseResult.h>
35 #include <FBaseSysLog.h>
36 #include <FBaseColAllElementsDeleter.h>
37 #include <FIoFile.h>
38 #include <FIoRegistry.h>
39
40 #include <FBase_StringConverter.h>
41 #include <FApp_AppInfo.h>
42 #include "FIo_FileImpl.h"
43 #include "FIo_NormalRegistry.h"
44 #include "FIo_SecureRegistry.h"
45 #include "FIo_RegistryCore.h"
46 #include "FIo_SecureIoUtil.h"
47
48 using namespace std;
49 using namespace Tizen::Base;
50 using namespace Tizen::Base::Utility;
51 using namespace Tizen::Base::Collection;
52
53 namespace Tizen { namespace Io
54 {
55
56 static const size_t _MAX_REG_OPENMODE_LENGTH = 2;
57
58 #define _REGISTRY_SECTION_MARKER_CHAR   L'#'
59 #define _REGISTRY_SECTION_VALUE_ASSIGNMENT_MARKER_CHAR L'='
60
61 class _RegistrySection
62         : public Object
63 {
64 public:
65         ~_RegistrySection(void);
66 private:
67         String __sectionName;
68         LinkedList __entryList;
69         friend class _RegistryCore;
70 };
71
72 _RegistrySection::~_RegistrySection(void)
73 {
74         __entryList.RemoveAll(true);
75 }
76
77 class _RegistryEntry
78         : public Object
79 {
80 public:
81         String entryName;
82         String entryValue;
83 };
84
85 _RegistryCore::_RegistryCore(void)
86         : _constructed(false)
87         , _read(false)
88         , _write(false)
89         , _truncate(false)
90         , _append(false)
91         , _update(false)
92         , _pBuffer(null)
93         , _length(0)
94         , __pFileImpl(null)
95 {
96 }
97
98 _RegistryCore::~_RegistryCore(void)
99 {
100         delete __pFileImpl;
101         delete[] _pBuffer;
102 }
103
104 bool
105 _RegistryCore::VerifyRegistryOpenMode(const char* pOpenMode)
106 {
107         if (pOpenMode == null)
108         {
109                 SysLog(NID_IO, "[E_INVALID_ARG] The specified openMode is null.");
110                 return false;
111         }
112
113         if (strlen(pOpenMode) > _MAX_REG_OPENMODE_LENGTH)
114         {
115                 SysLog(NID_IO, "[E_INVALID_ARG] The specified openMode (%s) is invalid.", pOpenMode);
116                 return false;
117         }
118
119         switch (pOpenMode[0])
120         {
121         case 'r':
122                 _read = true;
123                 break;
124         case 'w':
125                 _write = true;
126                 _truncate = true;
127                 break;
128         case 'a':
129                 _write = true;
130                 _append = true;
131                 break;
132         default:
133                 SysLog(NID_IO, "[E_INVALID_ARG] The specified openMode (%s) is invalid.", pOpenMode);
134                 return false;
135         }
136
137         switch (pOpenMode[1])
138         {
139         case '\0':
140                 break;
141         case '+':
142                 if (pOpenMode[2] == '\0')
143                 {
144                         _read = true;
145                         _write = true;
146                         break;
147                 }
148                 else
149                 {
150                         SysLog(NID_IO, "[E_INVALID_ARG] The specified openMode (%s) is invalid.", pOpenMode);
151                         return false;
152                 }
153         default:
154                 SysLog(NID_IO, "[E_INVALID_ARG] The specified openMode (%s) is invalid.", pOpenMode);
155                 return false;
156         }
157
158         return true;
159 }
160
161 result
162 _RegistryCore::Parse(void)
163 {
164         result r = E_SUCCESS;
165         wchar_t ch = '\0';
166         bool sectionFound = false;
167         String sectionName;
168         int length = 0;
169         unique_ptr<char[]> pEntryName(null);
170         unique_ptr<char[]> pEntryValue(null);
171         int firstTokenPos = 0;
172         String line;
173
174         if (_pBuffer == null)
175         {
176                 SysLog(NID_IO, "The buffer is empty.");
177                 return E_SUCCESS;
178         }
179
180         String inputStr = String((char*)_pBuffer);
181         StringTokenizer lineTok(inputStr, L"\n");
182
183         r = lineTok.GetNextToken(line);
184
185         while (r == E_SUCCESS)
186         {
187                 // skip empty lines
188                 if (line.GetLength() == 0)
189                 {
190                         r = lineTok.GetNextToken(line);
191                         continue;
192                 }
193
194                 // find registry section marker
195                 line.GetCharAt(0, ch);
196                 if (ch == _REGISTRY_SECTION_MARKER_CHAR)
197                 {
198                         sectionFound = true;
199
200                         // skip '#' and "\n' at the end
201                         r = line.SubString(1, line.GetLength() - 1, sectionName);
202                         SysTryCatch(NID_IO, !IsFailed(r), , r, "[%s] Propagated.", GetErrorMessage(r));
203
204                         // if End of the document follows section name without newline character.
205                         sectionName.GetCharAt(sectionName.GetLength() - 1, ch);
206                         if (ch == L'\n')
207                         {
208                                 sectionName.SetLength(sectionName.GetLength() - 1); //Remove '\n'
209                         }
210
211                         // for compatibility check if line contains  '\r' at the end
212                         sectionName.GetCharAt(sectionName.GetLength() - 1, ch);
213                         if (ch == L'\r')
214                         {
215                                 sectionName.SetLength(sectionName.GetLength() - 1); //Remove '\r'
216                         }
217
218                         //TODO: check if remaining data in sectionName is valid or not
219                         //after removing '#', '\n', and '\r', sectionName should contain at least 1 valid character
220                         SysTryCatch(NID_IO,
221                                            sectionName.GetLength() > 0, r = E_PARSING_FAILED, E_PARSING_FAILED,
222                                            "[E_PARSING_FAILED] Section length cannot be <2.");
223
224                         unique_ptr<char[]> pSectionName(_StringConverter::CopyToCharArrayN(sectionName));
225                         SysTryCatch(NID_IO, pSectionName != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
226                                            "[E_OUT_OF_MEMORY] The memory is insufficient.");
227
228                         if (!_RegistryCore::CheckSectionName(pSectionName.get()))
229                         {
230                                 SysTryCatch(NID_IO, false, r = E_PARSING_FAILED, E_PARSING_FAILED,
231                                                    "[E_PARSING_FAILED] Section name could not be parsed.");
232                         }
233
234                         r = _RegistryCore::AddSection(_sectionList, sectionName);
235                         SysTryCatch(NID_IO, !IsFailed(r), , r, "[%s] Propagated.", GetErrorMessage(r));
236                 }
237                 else    // not a section.. but may belongs to a section (entry)
238                 {
239                         // ignores blank lines
240                         line.GetCharAt(0, ch);
241                         if ((ch == L'\n') || (ch == L'\r'))
242                         {
243                                 r = lineTok.GetNextToken(line);
244                                 continue;
245                         }
246
247                         //TODO
248                         // Need to check for tabs, spaces in the beginning of each line
249
250                         // if no section found till now.. ignore
251                         if (sectionFound == false)
252                         {
253                                 r = lineTok.GetNextToken(line);
254                                 continue;
255                         }
256
257                         // if End of the document follows entry value without newline character.
258                         line.GetCharAt(line.GetLength() - 1, ch);
259                         if (ch == L'\n')
260                         {
261                                 line.SetLength(line.GetLength() - 1); //Remove '\n'
262                         }
263
264                         line.GetCharAt(line.GetLength() - 1, ch);
265                         if (ch == L'\r')
266                         {
267                                 line.SetLength(line.GetLength() - 1); //Remove '\r'
268                         }
269
270                         String entryName("");
271                         String entryVal("");
272
273                         // we will have sectionitem=value (or) sectionitem= (or) sectionitem
274                         // as our string. Break this into entry and value
275                         StringTokenizer strTok(line, L"=");
276
277                         // extract entry name
278                         if (strTok.HasMoreTokens())
279                         {
280                                 line.IndexOf(L'=', 0, firstTokenPos); // position of first occurance of '=' in a line
281                                 if (firstTokenPos == 0)
282                                 {
283                                         // entryName should not be empty. i.e., "=value"  or just '=' is invalid case
284                                         SysTryCatch(NID_IO, false, r = E_PARSING_FAILED, E_PARSING_FAILED,
285                                                            "[E_PARSING_FAILED] Entry name cannot be empty.");
286                                 }
287                                 else
288                                 {
289                                         strTok.GetNextToken(entryName);
290                                 }
291                         }
292                         else // missing '=' in  entry line or entry line does not seem to contain "xxx=xxx" format
293                         {
294                                 SysTryCatch(NID_IO, false, r = E_PARSING_FAILED, E_PARSING_FAILED, "[E_PARSING_FAILED] invalid entry Line found.");
295                         }
296
297                         // check if entry name contains invalid chars
298                         pEntryName.reset(_StringConverter::CopyToCharArrayN(entryName));
299                         SysTryCatch(NID_IO, pEntryName, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
300                                            "[E_OUT_OF_MEMORY] The memory is insufficient.");
301
302                         if (!_RegistryCore::CheckEntryName(pEntryName.get()))
303                         {
304                                 SysTryCatch(NID_IO, false, r = E_PARSING_FAILED, E_PARSING_FAILED,
305                                                    "[E_PARSING_FAILED] Entry name could not be parsed.");
306                         }
307
308                         line.SubString(firstTokenPos + 1, entryVal); // extract entry value
309
310                         // check if entry value contains invalid chars
311                         pEntryValue.reset(_StringConverter::CopyToCharArrayN(entryVal));
312                         SysTryCatch(NID_IO, pEntryValue, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
313                                            "[E_OUT_OF_MEMORY] The memory is insufficient.");
314
315                         length = strlen(pEntryValue.get());
316                         if (length > 0)
317                         {
318                                 if (!_RegistryCore::CheckEntryValue(pEntryValue.get()))
319                                 {
320                                         SysTryCatch(NID_IO, false, r = E_PARSING_FAILED, E_PARSING_FAILED,
321                                                            "[E_PARSING_FAILED] Entry value could not be parsed.");
322                                 }
323                         }
324
325                         // add the entry and value
326                         r = _RegistryCore::AddValue(_sectionList, sectionName, entryName, entryVal);
327                         SysTryCatch(NID_IO, !IsFailed(r), , r, "[%s] Propagated.", GetErrorMessage(r));
328                 }
329                 r = lineTok.GetNextToken(line);
330         } // while()
331
332         if (r == E_OUT_OF_RANGE)
333         {
334                 r = E_SUCCESS;
335         }
336
337         // fall through
338 CATCH:
339
340         if (r == E_PARSING_FAILED && Tizen::App::_AppInfo::IsOspCompat() == false)
341         {
342                 r = E_INVALID_FORMAT;
343         }
344
345         SysLog(NID_IO, "[%s] exception occurred.", GetErrorMessage(r));
346         return r;
347 }
348
349 result
350 _RegistryCore::Load(const String& regPath, const char* pOpenMode)
351 {
352         result r = E_SUCCESS;
353         delete[] _pBuffer; //clear existing buffer
354         _pBuffer = null;
355         _length = 0;
356
357         // open registry file
358         unique_ptr<_FileImpl> pFileImpl(new (std::nothrow) _FileImpl());
359         SysTryReturnResult(NID_IO, pFileImpl != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
360
361         r = pFileImpl->Construct(regPath, pOpenMode, null);
362         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Constructing the file has failed.", GetErrorMessage(r));
363
364         // reset the section list to be sure that its empty
365         _sectionList.RemoveAll(true);
366
367         if (_truncate == false)
368         {
369                 // load the registry file
370                 r = pFileImpl->ReadN((char**)&_pBuffer, _length);
371                 if (_length > 0)
372                 {
373                         _length--;
374                 }
375         }
376
377         __pFileImpl = pFileImpl.release();
378
379         return r;
380 }
381
382 result
383 _RegistryCore::AddSection(const String& sectionName)
384 {
385         SysAssertf(_constructed == true, "Not yet constructed. Construct() should be called before use.\n");
386
387         result r = E_SUCCESS;
388         bool sectionFound = false;
389
390         // Get section information
391         unique_ptr<IEnumerator> pEnum(_sectionList.GetEnumeratorN());
392         if (pEnum == null)
393         {
394                 return GetLastResult();
395         }
396
397         while (pEnum->MoveNext() == E_SUCCESS)
398         {
399                 _RegistrySection* pRegSection = dynamic_cast <_RegistrySection*>(pEnum->GetCurrent());
400                 SysTryReturn(NID_IO, pRegSection != null, GetLastResult(), GetLastResult(), "[%s] Propagated.",
401                                    GetErrorMessage(GetLastResult()));
402
403                 if (pRegSection->__sectionName == sectionName)
404                 {
405                         sectionFound = true;
406                         break;
407                 }
408         }
409
410         if (sectionFound == true)
411         {
412                 return E_SECTION_ALREADY_EXIST;
413         }
414
415         // create a key with section name
416         unique_ptr<_RegistrySection> pRegSection(new (std::nothrow) _RegistrySection());
417         SysTryReturnResult(NID_IO, pRegSection != null, E_OUT_OF_MEMORY,
418                            "The memory is insufficient.");
419
420         pRegSection->__sectionName = sectionName;
421
422         // add new section and section-entry map
423         r = _sectionList.Add(*(pRegSection.release()));
424         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagated.", GetErrorMessage(r));
425
426         _update = true;
427         return E_SUCCESS;
428 }
429
430 result
431 _RegistryCore::RemoveSection(const String& sectionName)
432 {
433         SysAssertf(_constructed == true, "Not yet constructed. Construct() should be called before use.\n");
434
435         result r = E_SUCCESS;
436         _RegistrySection* pRegSection = null;
437         bool sectionFound = false;
438
439         if (_sectionList.GetCount() == 0)
440         {
441                 return E_SECTION_NOT_FOUND;
442         }
443
444         // Get section information
445         unique_ptr<IEnumerator> pEnum(_sectionList.GetEnumeratorN());
446         if (pEnum == null)
447         {
448                 return GetLastResult();
449         }
450
451         while (pEnum->MoveNext() == E_SUCCESS)
452         {
453                 pRegSection = dynamic_cast< _RegistrySection* >(pEnum->GetCurrent());
454                 SysTryReturn(NID_IO, pRegSection != null, GetLastResult(), GetLastResult(), "[%s] Propagating.",
455                                    GetErrorMessage(GetLastResult()));
456
457                 if (pRegSection->__sectionName == sectionName)
458                 {
459                         sectionFound = true;
460                         break;
461                 }
462         }
463
464         if (sectionFound == false)
465         {
466                 return E_SECTION_NOT_FOUND;
467         }
468
469         r = _sectionList.Remove(*pRegSection, true);
470         SysTryReturnResult(NID_IO, !IsFailed(r), E_IO, "system error");
471
472         _update = true;
473         return E_SUCCESS;
474 }
475
476 result
477 _RegistryCore::GetSectionListN(IList** pRetList)
478 {
479         result r = E_SUCCESS;
480         unique_ptr<IEnumerator> pEnum(null);
481         _RegistrySection* pSection = null;
482
483         SysAssertf(_constructed == true, "Not yet constructed. Construct() should be called before use.\n");
484         SysTryReturnResult(NID_IO, pRetList != null, E_INVALID_ARG, "pList cannot be null.");
485
486         // construct an array list to be returned
487         unique_ptr<ArrayList, AllElementsDeleter> pSectionList(new (std::nothrow) ArrayList());
488         SysTryReturnResult(NID_IO, pSectionList != null, E_OUT_OF_MEMORY,
489                            "The memory is insufficient.");
490
491         r = pSectionList->Construct();
492         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagated.", GetErrorMessage(r));
493
494         // if no sectons, return empty list
495         if (_sectionList.GetCount() == 0)
496         {
497                 *pRetList = pSectionList.release();
498                 return E_SUCCESS;
499         }
500
501         // copy from class section list to the new list and return
502         pEnum.reset(_sectionList.GetEnumeratorN());
503         SysTryReturn(NID_IO, pEnum != null, GetLastResult(), GetLastResult(), "[%s] Section list is empty.", GetErrorMessage(GetLastResult()));
504
505         while (pEnum->MoveNext() == E_SUCCESS)
506         {
507                 pSection = dynamic_cast <_RegistrySection*>(pEnum->GetCurrent());
508                 SysTryReturn(NID_IO, pSection != null, GetLastResult(), GetLastResult(), "[%s] Propagated.",
509                                    GetErrorMessage(GetLastResult()));
510
511                 unique_ptr<String> pSectionName(new (std::nothrow) String(pSection->__sectionName));
512                 SysTryReturnResult(NID_IO, pSectionName != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
513
514                 r = pSectionList->Add(*(pSectionName.release()));
515                 SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagated.", GetErrorMessage(r));
516         }
517
518         *pRetList = pSectionList.release();
519
520         return E_SUCCESS;
521 }
522
523 result
524 _RegistryCore::GetEntryList(const String& sectionName, Collection::HashMap& retMap)
525 {
526         result r = E_SUCCESS;
527         unique_ptr<IEnumerator> pEnum(null);
528         unique_ptr<String> pKeyEntryStr(null);
529         unique_ptr<String> pKeyValStr(null);
530         bool sectionFound = false;
531         _RegistrySection* pRegSection = null;
532         _RegistryEntry* pRegEntry = null;
533
534         SysAssertf(_constructed == true, "Not yet constructed. Construct() should be called before use.\n");
535
536         if (_sectionList.GetCount() == 0)
537         {
538                 return E_SECTION_NOT_FOUND;
539         }
540
541         // Get section information
542         pEnum.reset(_sectionList.GetEnumeratorN());
543         SysTryReturnResult(NID_IO, pEnum != null, E_SYSTEM, "Section list is empty.");
544
545         while (pEnum->MoveNext() == E_SUCCESS)
546         {
547                 pRegSection = dynamic_cast <_RegistrySection*>(pEnum->GetCurrent());
548                 SysTryReturn(NID_IO, pRegSection != null, GetLastResult(), GetLastResult(), "[%s] Propagated.",
549                                    GetErrorMessage(GetLastResult()));
550
551                 if (pRegSection->__sectionName == sectionName)
552                 {
553                         sectionFound = true;
554                         break;
555                 }
556         }
557
558         if (sectionFound == false)
559         {
560                 return E_SECTION_NOT_FOUND;
561         }
562
563         // copy from item list to the new list and return
564         pEnum.reset((pRegSection->__entryList).GetEnumeratorN());
565         SysTryReturn(NID_IO, pEnum != null, GetLastResult(), GetLastResult(), "[%s] Propagated.",
566                                            GetErrorMessage(GetLastResult()));
567
568         while (pEnum->MoveNext() == E_SUCCESS)
569         {
570                 pRegEntry = dynamic_cast <_RegistryEntry*>(pEnum->GetCurrent());
571                 SysTryReturn(NID_IO, pRegEntry != null, GetLastResult(), GetLastResult(), "[%s] Propagated.",
572                                    GetErrorMessage(GetLastResult()));
573
574                 pKeyEntryStr.reset(new (std::nothrow) String((pRegEntry->entryName)));
575                 SysTryCatch(NID_IO, pKeyEntryStr != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
576                                 "[E_OUT_OF_MEMORY] The memory is insufficient.");
577                 pKeyValStr.reset(new (std::nothrow) String((pRegEntry->entryValue)));
578                 SysTryCatch(NID_IO, pKeyValStr != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
579                                 "[E_OUT_OF_MEMORY] The memory is insufficient.");
580
581                 r = retMap.Add(*(pKeyEntryStr.release()), *(pKeyValStr.release()));
582                 SysTryCatch(NID_IO, !IsFailed(r), , r, "[%s] Propagated.", GetErrorMessage(r));
583         }
584
585         return E_SUCCESS;
586
587 CATCH:
588         retMap.RemoveAll(true);
589
590         return r;
591 }
592
593 result
594 _RegistryCore::GetEntryListN(const String& sectionName, HashMap** pRetList)
595 {
596         result r = E_SUCCESS;
597
598         SysAssertf(_constructed == true, "Not yet constructed. Construct() should be called before use.\n");
599         SysTryReturnResult(NID_IO, pRetList != null, E_INVALID_ARG, "pRetList cannot be null.");
600
601         // construct an array list to be returned
602         unique_ptr<HashMap, AllElementsDeleter> pEntryList(new (std::nothrow) HashMap());
603         SysTryReturnResult(NID_IO, pEntryList != null, E_OUT_OF_MEMORY,
604                         "The memory is insufficient.");
605         r = pEntryList->Construct();
606         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagated.", GetErrorMessage(r));
607         r = GetEntryList(sectionName, *(pEntryList.get()));
608         *pRetList = pEntryList.release();
609
610         return r;
611 }
612
613 IMap*
614 _RegistryCore::GetAllEntriesN(const String& sectionName)
615 {
616         result r = E_SUCCESS;
617         HashMap* pMap = null;
618
619         r = GetEntryListN(sectionName, &pMap);
620         SysTryCatch(NID_IO, !IsFailed(r), , r, "[%s] Propagated.", GetErrorMessage(r));
621
622         SetLastResult(E_SUCCESS);
623         return pMap;
624
625 CATCH:
626         SetLastResult(r);
627         return null;
628 }
629
630 IList*
631 _RegistryCore::GetAllEntryNamesN(const String& sectionName)
632 {
633         result r = E_SUCCESS;
634
635         unique_ptr<ArrayList, AllElementsDeleter> pEntryList(new (std::nothrow) ArrayList());
636         SysTryReturn(NID_IO, pEntryList != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
637
638         r = pEntryList->Construct();
639         SysTryReturn(NID_IO, !IsFailed(r), null, r, "[%s] Propagated.", GetErrorMessage(r));
640
641         unique_ptr<IMap, AllElementsDeleter> pMap(this->GetAllEntriesN(sectionName));
642         SysTryReturn(NID_IO, pMap != null, null, GetLastResult(), "[%s] Getting all entries was failed.",
643                         GetErrorMessage(GetLastResult()));
644
645         unique_ptr<IMapEnumerator> pMapEnum(pMap->GetMapEnumeratorN());
646         SysTryReturn(NID_IO, pMapEnum, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
647         while (pMapEnum->MoveNext() == E_SUCCESS)
648         {
649                 String* pKey = dynamic_cast< String* >(pMapEnum->GetKey());
650                 SysTryReturn(NID_IO, pKey != null, null, E_IO, "[E_OUT_OF_MEMORY] The system error occurred.");
651
652                 String* pEntryName = new (std::nothrow) String(*pKey);
653                 SysTryReturn(NID_IO, pEntryName != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
654
655                 r = pEntryList->Add(*pEntryName);
656                 SysTryReturn(NID_IO, !IsFailed(r), null, r, "[%s] Propagated.", GetErrorMessage(r));
657         }
658
659         SetLastResult(E_SUCCESS);
660         return pEntryList.release();
661 }
662
663 result
664 _RegistryCore::GetValue(const String& sectionName, const String& entryName, String& valStr)
665 {
666         bool sectionFound = false;
667         bool entryFound = false;
668         _RegistrySection* pRegSection = null;
669         _RegistryEntry* pRegEntry = null;
670
671         SysAssertf(_constructed == true, "Not yet constructed. Construct() should be called before use.\n");
672
673         if (_sectionList.GetCount() == 0)
674         {
675                 return E_SECTION_NOT_FOUND;
676         }
677
678         // Get section information
679         unique_ptr<IEnumerator> pEnum(_sectionList.GetEnumeratorN());
680         if (pEnum == null)
681         {
682                 return GetLastResult();
683         }
684
685         while (pEnum->MoveNext() == E_SUCCESS)
686         {
687                 pRegSection = dynamic_cast <_RegistrySection*>(pEnum->GetCurrent());
688                 SysTryReturn(NID_IO, pRegSection != null, GetLastResult(), GetLastResult(), "[%s] Propagated.",
689                                    GetErrorMessage(GetLastResult()));
690
691                 if (pRegSection->__sectionName == sectionName)
692                 {
693                         sectionFound = true;
694                         break;
695                 }
696         }
697
698         if (sectionFound == false)
699         {
700                 return E_SECTION_NOT_FOUND;
701         }
702
703         pEnum.reset(pRegSection->__entryList.GetEnumeratorN());
704         if (pEnum == null)
705         {
706                 return GetLastResult();
707         }
708
709         while (pEnum->MoveNext() == E_SUCCESS)
710         {
711                 pRegEntry = dynamic_cast <_RegistryEntry*>(pEnum->GetCurrent());
712                 SysTryReturn(NID_IO, pRegEntry != null, GetLastResult(), GetLastResult(), "[%s] Propagated.",
713                                    GetErrorMessage(GetLastResult()));
714
715                 if (pRegEntry->entryName == entryName)
716                 {
717                         valStr = pRegEntry->entryValue;
718                         entryFound = true;
719                         break;
720                 }
721         }
722
723         SysTryLog(NID_IO, entryFound, "Entry not found");
724
725         return((entryFound == true) ? E_SUCCESS : E_KEY_NOT_FOUND);
726 }
727
728 result
729 _RegistryCore::AddValue(const String& sectionName, const String& entryName, const String& valStr)
730 {
731         result r = E_SUCCESS;
732         bool sectionFound = false;
733         bool entryFound = false;
734         _RegistrySection* pRegSection = null;
735         int length = 0;
736
737         SysAssertf(_constructed == true, "Not yet constructed. Construct() should be called before use.\n");
738
739         // Get section information
740         unique_ptr<IEnumerator> pEnum(_sectionList.GetEnumeratorN());
741         if (pEnum == null)
742         {
743                 return GetLastResult();
744         }
745
746         while (pEnum->MoveNext() == E_SUCCESS)
747         {
748                 pRegSection = dynamic_cast <_RegistrySection*>(pEnum->GetCurrent());
749                 SysTryReturn(NID_IO, pRegSection != null, GetLastResult(), GetLastResult(), "[%s] Propagated.",
750                                    GetErrorMessage(GetLastResult()));
751
752                 if (pRegSection->__sectionName == sectionName)
753                 {
754                         sectionFound = true;
755                         break;
756                 }
757         }
758
759         if (sectionFound == false)
760         {
761                 return E_SECTION_NOT_FOUND;
762         }
763
764         pEnum.reset(pRegSection->__entryList.GetEnumeratorN());
765         if (pEnum == null)
766         {
767                 return GetLastResult();
768         }
769
770         while (pEnum->MoveNext() == E_SUCCESS)
771         {
772                 _RegistryEntry* pRegEntry = dynamic_cast <_RegistryEntry*>(pEnum->GetCurrent());
773                 SysTryReturn(NID_IO, pRegEntry != null, GetLastResult(), GetLastResult(), "[%s] Propagated.",
774                                    GetErrorMessage(GetLastResult()));
775
776                 if (pRegEntry->entryName == entryName)
777                 {
778                         entryFound = true;
779                         break;
780                 }
781         }
782
783         if (entryFound == true)
784         {
785                 return E_KEY_ALREADY_EXIST;
786         }
787
788         unique_ptr<_RegistryEntry> pRegEntry(new (std::nothrow) _RegistryEntry());
789         SysTryReturnResult(NID_IO, pRegEntry != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
790
791         unique_ptr<char[]> pEntryName(_StringConverter::CopyToCharArrayN(entryName));
792         SysTryReturnResult(NID_IO, pEntryName != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
793
794         length = strlen(pEntryName.get());
795         if (!_RegistryCore::CheckEntryName(pEntryName.get()))
796         {
797                 SysTryReturnResult(NID_IO, false, E_PARSING_FAILED, "Entry name could not be parsed.");
798         }
799
800         unique_ptr<char[]> pEntryValue(_StringConverter::CopyToCharArrayN(valStr));
801         SysTryReturnResult(NID_IO, pEntryValue != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
802
803         length = strlen(pEntryValue.get());
804         if (length > 0 && !_RegistryCore::CheckEntryValue(pEntryValue.get()))
805         {
806                 SysTryReturnResult(NID_IO, false, E_PARSING_FAILED, "Entry value could not be parsed.");
807         }
808
809         pRegEntry->entryName = entryName;
810         pRegEntry->entryValue = valStr;
811
812         r = pRegSection->__entryList.Add(*(pRegEntry.release()));
813         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagated.", GetErrorMessage(r));
814
815         _update = true;
816         return E_SUCCESS;
817 }
818
819 result
820 _RegistryCore::SetValue(const String& sectionName, const String& entryName, const String& valStr)
821 {
822         result r = E_SUCCESS;
823         bool sectionFound = false;
824         bool entryFound = false;
825         _RegistryEntry* pRegEntry = null;
826         _RegistrySection* pRegSection = null;
827         int length = 0;
828         int entryIndex = 0;
829
830         SysAssertf(_constructed == true, "Not yet constructed. Construct() should be called before use.\n");
831
832         if (_sectionList.GetCount() == 0)
833         {
834                 return E_SECTION_NOT_FOUND;
835         }
836
837         // Get section information
838         unique_ptr<IEnumerator> pEnum(_sectionList.GetEnumeratorN());
839         if (pEnum == null)
840         {
841                 return GetLastResult();
842         }
843
844         while (pEnum->MoveNext() == E_SUCCESS)
845         {
846                 pRegSection = dynamic_cast< _RegistrySection* >(pEnum->GetCurrent());
847                 SysTryReturn(NID_IO, pRegSection != null, GetLastResult(), GetLastResult(), "[%s] Propagated.",
848                                    GetErrorMessage(GetLastResult()));
849
850                 if (pRegSection->__sectionName == sectionName)
851                 {
852                         sectionFound = true;
853                         break;
854                 }
855         }
856
857         if (sectionFound == false)
858         {
859                 return E_SECTION_NOT_FOUND;
860         }
861
862         pEnum.reset(pRegSection->__entryList.GetEnumeratorN());
863         if (pEnum == null)
864         {
865                 return GetLastResult();
866         }
867
868         while (pEnum->MoveNext() == E_SUCCESS)
869         {
870                 pRegEntry = dynamic_cast< _RegistryEntry* >(pEnum->GetCurrent());
871                 SysTryReturn(NID_IO, pRegEntry != null, GetLastResult(), GetLastResult(), "[%s] Propagated.",
872                                    GetErrorMessage(GetLastResult()));
873
874                 if (pRegEntry->entryName == entryName)
875                 {
876                         entryFound = true;
877                         break;
878                 }
879                 entryIndex++;
880         }
881
882         if (entryFound == false)
883         {
884                 return E_KEY_NOT_FOUND;
885         }
886
887         if (valStr.GetLength() > 0)
888         {
889                 unique_ptr<char[]> pEntryValue(_StringConverter::CopyToCharArrayN(valStr));
890                 SysTryReturnResult(NID_IO, pEntryValue != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
891
892                 length = strlen(pEntryValue.get());
893                 if (!_RegistryCore::CheckEntryValue(pEntryValue.get()))
894                 {
895                         return E_PARSING_FAILED;
896                 }
897         }
898
899         pRegEntry->entryValue = valStr;
900         r = pRegSection->__entryList.SetAt(*pRegEntry, entryIndex);
901         SysTryReturnResult(NID_IO, !IsFailed(r), E_IO, "system error");
902
903         _update = true;
904         return E_SUCCESS;
905 }
906
907 result
908 _RegistryCore::RemoveValue(const String& sectionName, const String& entryName)
909 {
910         result r = E_SUCCESS;
911         bool sectionFound = false;
912         bool entryFound = false;
913         _RegistryEntry* pRegEntry = null;
914         _RegistrySection* pRegSection = null;
915
916         SysAssertf(_constructed == true, "Not yet constructed. Construct() should be called before use.\n");
917
918         if (_sectionList.GetCount() <= 0)
919         {
920                 return E_SECTION_NOT_FOUND;
921         }
922
923         // Get section information
924         unique_ptr<IEnumerator> pEnum(_sectionList.GetEnumeratorN());
925         if (pEnum == null)
926         {
927                 return E_SECTION_NOT_FOUND;
928         }
929
930         while (pEnum->MoveNext() == E_SUCCESS)
931         {
932                 pRegSection = dynamic_cast <_RegistrySection*>(pEnum->GetCurrent());
933                 SysTryReturn(NID_IO, pRegSection != null, GetLastResult(), GetLastResult(), "[%s] Propagated.",
934                                    GetErrorMessage(GetLastResult()));
935
936                 if (pRegSection->__sectionName == sectionName)
937                 {
938                         sectionFound = true;
939                         break;
940                 }
941         }
942
943         if (sectionFound == false)
944         {
945                 return E_SECTION_NOT_FOUND;
946         }
947
948         pEnum.reset(pRegSection->__entryList.GetEnumeratorN());
949         if (pEnum == null)
950         {
951                 return E_SECTION_NOT_FOUND;
952         }
953
954         while (pEnum->MoveNext() == E_SUCCESS)
955         {
956                 pRegEntry = dynamic_cast <_RegistryEntry*>(pEnum->GetCurrent());
957                 SysTryReturn(NID_IO, pRegEntry != null, GetLastResult(), GetLastResult(), "[%s] Propagated.",
958                                    GetErrorMessage(GetLastResult()));
959
960                 if (pRegEntry->entryName == entryName)
961                 {
962                         entryFound = true;
963                         break;
964                 }
965         }
966
967         if (entryFound == false)
968         {
969                 return E_KEY_NOT_FOUND;
970         }
971
972         r = pRegSection->__entryList.Remove(*pRegEntry, true);
973         SysTryReturnResult(NID_IO, !IsFailed(r), E_IO, "system error");
974
975         _update = true;
976         return E_SUCCESS;
977 }
978
979 result
980 _RegistryCore::Flush(void)
981 {
982         return E_SUCCESS;
983 }
984
985 result
986 _RegistryCore::Write(void)
987 {
988         SysAssertf(_constructed == true, "Not yet constructed. Construct() should be called before use.\n");
989
990         if (_pBuffer == null)
991         {
992                 SysLog(NID_IO, "The buffer is empty.");
993                 return E_SUCCESS;
994         }
995
996         result r = E_SUCCESS;
997
998         String openMode(L"w+");
999         unique_ptr<_FileImpl> pFileImpl(new (std::nothrow) _FileImpl);
1000         SysTryReturnResult(NID_IO, pFileImpl != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
1001
1002         //TODO: Secure mode is to be handled
1003         r = pFileImpl->Construct(_regPath, "w+", null);
1004         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagated.", GetErrorMessage(r));
1005
1006         r = pFileImpl->Write(_pBuffer, _length);
1007         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagated.", GetErrorMessage(r));
1008
1009         r = pFileImpl->Flush();
1010         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagated.", GetErrorMessage(r));
1011
1012         return r;
1013 }
1014
1015 result
1016 _RegistryCore::PrepareToWrite(void)
1017 {
1018         SysAssertf(_constructed == true, "Not yet constructed. Construct() should be called before use.\n");
1019
1020         result r = E_SUCCESS;
1021         _RegistryEntry* pRegEntry = null;
1022         _RegistrySection* pRegSection = null;
1023         String inputBuffer;
1024
1025         delete[] _pBuffer; //clear existing buffer
1026         _pBuffer = null;
1027         _length = 0;
1028
1029         if (_write == false)
1030         {
1031                 SysLog(NID_IO, "[E_ILLEGAL_ACCESS] Registry cannot be flushed as it was opened in read only mode.");
1032                 return E_ILLEGAL_ACCESS;
1033         }
1034
1035         // if no sections, do nothing
1036         if (_sectionList.GetCount() == 0)
1037         {
1038                 unique_ptr<char[]> pFilePath(_StringConverter::CopyToCharArrayN(_regPath));
1039                 truncate(pFilePath.get(), 0);
1040
1041                 return E_SUCCESS;
1042         }
1043
1044         // write the registry map to a file
1045         // Get section information
1046         unique_ptr<IEnumerator> pSectionEnum(_sectionList.GetEnumeratorN());
1047         SysTryReturn(NID_IO, pSectionEnum != null, GetLastResult(), GetLastResult(), "[%s] Section list is empty.",
1048                            GetErrorMessage(GetLastResult()));
1049
1050         while (pSectionEnum->MoveNext() == E_SUCCESS)
1051         {
1052                 // get section name
1053                 pRegSection = dynamic_cast <_RegistrySection*>(pSectionEnum->GetCurrent());
1054                 SysTryReturn(NID_IO, pRegSection != null, GetLastResult(), GetLastResult(), "[%s] Propagated.",
1055                                    GetErrorMessage(GetLastResult()));
1056
1057                 // write section name to file
1058                 r = inputBuffer.Append(String(L"#" + pRegSection->__sectionName + String(L'\n')));
1059                 SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagated.", GetErrorMessage(r));
1060
1061                 // read the entries for this section
1062                 unique_ptr<IEnumerator> pEntryEnum(pRegSection->__entryList.GetEnumeratorN());
1063                 SysTryReturn(NID_IO, pSectionEnum != null, GetLastResult(), GetLastResult(), "[%s] Entry list is empty.",
1064                                    GetErrorMessage(GetLastResult()));
1065
1066                 while (pEntryEnum->MoveNext() == E_SUCCESS)
1067                 {
1068                         pRegEntry = dynamic_cast <_RegistryEntry*>(pEntryEnum->GetCurrent());
1069                         SysTryReturn(NID_IO, pRegEntry != null, GetLastResult(), GetLastResult(), "[%s] Propagated.",
1070                                            GetErrorMessage(GetLastResult()));
1071
1072                         // write entry name to file
1073                         r = inputBuffer.Append(pRegEntry->entryName + String(L"=" + pRegEntry->entryValue + String(L'\n')));
1074                         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagated.", GetErrorMessage(r));
1075                 }
1076
1077         }
1078
1079         _pBuffer = (byte*)_StringConverter::CopyToCharArrayN(inputBuffer);
1080         SysTryReturn(NID_IO, _pBuffer != null, GetLastResult(), GetLastResult(), "[%s] Propagated.",
1081                                                    GetErrorMessage(GetLastResult()));
1082
1083         _length = strlen((char*)_pBuffer);
1084
1085         return r;
1086 }
1087
1088 int
1089 _RegistryCore::GetSectionIndex(const String& sectionName)
1090 {
1091         bool sectionFound = false;
1092         _RegistrySection* pRegSection = null;
1093         int index = 0;
1094
1095         SysAssertf(_constructed == true, "Not yet constructed. Construct() should be called before use.\n");
1096         SysTryReturn(NID_IO, sectionName.GetLength() > 0, -1, E_INVALID_ARG,
1097                            "[E_INVALID_ARG] sectionName.GetLength() <= 0");
1098
1099         SysTryReturn(NID_IO, _sectionList.GetCount() > 0, -1, E_SECTION_NOT_FOUND, "[E_SECTION_NOT_FOUND] Section not found.");
1100
1101         // Get section information
1102         unique_ptr<IEnumerator> pEnum(_sectionList.GetEnumeratorN());
1103         SysTryReturn(NID_IO, pEnum != null, GetLastResult(), GetLastResult(), "[%s] Section list is empty.",
1104                            GetErrorMessage(GetLastResult()));
1105
1106         while (pEnum->MoveNext() == E_SUCCESS)
1107         {
1108                 pRegSection = dynamic_cast <_RegistrySection*>(pEnum->GetCurrent());
1109                 SysTryReturn(NID_IO, pRegSection != null, -1, GetLastResult(), "[%s] Propagated.",
1110                                    GetErrorMessage(GetLastResult()));
1111
1112                 if (pRegSection->__sectionName == sectionName)
1113                 {
1114                         sectionFound = true;
1115                         break;
1116                 }
1117                 index++;
1118         }
1119
1120         if (sectionFound == false)
1121         {
1122                 return E_SECTION_NOT_FOUND;
1123         }
1124
1125         SetLastResult(E_SUCCESS);
1126         return index;
1127 }
1128
1129 void
1130 _RegistryCore::Removekey(const String& sectionName, const String& keyName)
1131 {
1132         result r = E_SUCCESS;
1133         int sectionIndex = -1;
1134         int entryIndex = -1;
1135
1136         sectionIndex = GetSectionIndex(sectionName);
1137         r = GetLastResult();
1138         SysTryReturnVoidResult(NID_IO, !IsFailed(r), r, "[%s] Propagated.", GetErrorMessage(r));
1139
1140         entryIndex = GetEntryIndex(sectionIndex, keyName);
1141         r = GetLastResult();
1142         SysTryReturnVoidResult(NID_IO, !IsFailed(r), r, "[%s] Propagated.", GetErrorMessage(r));
1143
1144         RemoveEntry(sectionIndex, entryIndex);
1145         r = GetLastResult();
1146         SysTryReturnVoidResult(NID_IO, !IsFailed(r), r, "[%s] Propagated.", GetErrorMessage(r));
1147
1148         SetLastResult(E_SUCCESS);
1149         return;
1150 }
1151
1152 int
1153 _RegistryCore::GetAllSectionCount(void)
1154 {
1155         SysAssertf(_constructed == true, "Not yet constructed. Construct() should be called before use.\n");
1156
1157         SetLastResult(E_SUCCESS);
1158         return _sectionList.GetCount();
1159 }
1160
1161 int
1162 _RegistryCore::GetAllEntryCount(int sectionIndex)
1163 {
1164         _RegistrySection* pRegSection = null;
1165         int listSize = 0;
1166
1167         SysAssertf(_constructed == true, "Not yet constructed. Construct() should be called before use.\n");
1168         SysTryReturn(NID_IO, sectionIndex >= 0, 0, E_INVALID_ARG, "[E_INVALID_ARG] sectionIndex < 0.");
1169         listSize = _sectionList.GetCount();
1170         SysTryReturn(NID_IO, listSize > 0, 0, E_SECTION_NOT_FOUND, "[E_INVALID_ARG] section listSize <= 0.");
1171         SysTryReturn(NID_IO, sectionIndex >= listSize, 0, E_SECTION_NOT_FOUND,
1172                            "[E_INVALID_ARG] sectionIndex > listSize.");
1173
1174         pRegSection = (_RegistrySection*) GetSectionByIndex(sectionIndex);
1175         SysTryReturn(NID_IO, pRegSection != null, 0, E_SECTION_NOT_FOUND,
1176                            "[E_SECTION_NOT_FOUND] section was not found.");
1177
1178         SetLastResult(E_SUCCESS);
1179         return pRegSection->__entryList.GetCount();
1180 }
1181
1182 void
1183 _RegistryCore::RemoveEntry(int sectionIndex, int entryIndex)
1184 {
1185         result r = E_SUCCESS;
1186         int listSize = 0;
1187         int entryListSize = 0;
1188         _RegistrySection* pRegSection = null;
1189
1190         SysAssertf(_constructed == true, "Not yet constructed. Construct() should be called before use.\n");
1191         SysTryReturnVoidResult(NID_IO, sectionIndex >= 0, E_INVALID_ARG, "[E_INVALID_ARG] sectionIndex < 0.");
1192         SysTryReturnVoidResult(NID_IO, entryIndex >= 0, E_INVALID_ARG, "[E_INVALID_ARG] entryIndex < 0.");
1193
1194         listSize = _sectionList.GetCount();
1195         SysTryReturnVoidResult(NID_IO, listSize > 0, E_SECTION_NOT_FOUND,
1196                            "[E_SECTION_NOT_FOUND] section listSize <= 0.");
1197         SysTryReturnVoidResult(NID_IO, sectionIndex < listSize, E_SECTION_NOT_FOUND,
1198                            "[E_SECTION_NOT_FOUND] sectionIndex >= listSize.");
1199
1200         pRegSection = (_RegistrySection*) GetSectionByIndex(sectionIndex);
1201         SysTryReturnVoidResult(NID_IO, pRegSection != null, E_SECTION_NOT_FOUND,
1202                            "[E_SECTION_NOT_FOUND] Section at index (%d) not found.", sectionIndex);
1203
1204         r = GetLastResult();
1205         SysTryReturnVoidResult(NID_IO, !IsFailed(r), r,"[%s] Propagated.", GetErrorMessage(r));
1206
1207         entryListSize = pRegSection->__entryList.GetCount();
1208         SysTryReturnVoidResult(NID_IO, (entryListSize > 0 || entryIndex < entryListSize), E_KEY_NOT_FOUND,
1209                            "[E_KEY_NOT_FOUND] entryListSize is 0 or entryIndex >= entryListSize.");
1210
1211         r = pRegSection->__entryList.RemoveAt(entryIndex, true);
1212         SysTryReturnVoidResult(NID_IO, !IsFailed(r), r, "[%s] Propagated.", GetErrorMessage(r));
1213
1214         SetLastResult(E_SUCCESS);
1215 }
1216
1217 void
1218 _RegistryCore::ModifyEntryValue(int sectionIndex, int entryIndex, _RegValueType type, const void* pValue, int size)
1219 {
1220         SetLastResult(E_UNSUPPORTED_OPERATION);
1221 }
1222
1223 int
1224 _RegistryCore::GetEntryIndex(int sectionIndex, const String& entryName)
1225 {
1226         _RegistrySection* pRegSection = null;
1227         _RegistryEntry* pRegEntry = null;
1228         int listSize = 0;
1229         bool entryFound = false;
1230         int entryIndex = -1;
1231
1232         SysAssertf(_constructed == true, "Not yet constructed. Construct() should be called before use.\n");
1233         SysTryReturn(NID_IO, sectionIndex >= 0, -1, E_INVALID_ARG, "[E_INVALID_ARG]sectionIndex < 0.");
1234         SysTryReturn(NID_IO, entryName.GetLength() > 0, -1, E_INVALID_ARG, "[E_INVALID_ARG]entryName length < 0.");
1235
1236         listSize = _sectionList.GetCount();
1237         SysTryReturn(NID_IO, listSize > 0, -1, E_SECTION_NOT_FOUND,
1238                            "[E_SECTION_NOT_FOUND]Registry section list is empty.");
1239         SysTryReturn(NID_IO, sectionIndex < listSize, -1, E_SECTION_NOT_FOUND,
1240                            "[E_SECTION_NOT_FOUND]sectionIndex >= listSize.");
1241
1242         pRegSection = (_RegistrySection*) GetSectionByIndex(sectionIndex);
1243         SysTryReturn(NID_IO, pRegSection != null, -1, E_SECTION_NOT_FOUND,
1244                            "[E_SECTION_NOT_FOUND] Section at index (%d) not found.", sectionIndex);
1245
1246         // read the entries for this section
1247         unique_ptr<IEnumerator> pEntryEnum(pRegSection->__entryList.GetEnumeratorN());
1248         SysTryReturn(NID_IO, pEntryEnum != null, -1, GetLastResult(), "[%s] Entry list is empty.",
1249                            GetErrorMessage(GetLastResult()));
1250
1251         entryIndex = 0;
1252         while (pEntryEnum->MoveNext() == E_SUCCESS)
1253         {
1254                 pRegEntry = dynamic_cast <_RegistryEntry*>(pEntryEnum->GetCurrent());
1255                 SysTryReturn(NID_IO, pRegEntry != null, -1, GetLastResult(), "[%s] Propagated.",
1256                                    GetErrorMessage(GetLastResult()));
1257
1258                 if (entryName == pRegEntry->entryName)
1259                 {
1260                         entryFound = true;
1261                         break;
1262                 }
1263                 entryIndex++;
1264         }
1265
1266         SysTryReturn(NID_IO, entryFound != false, -1, E_KEY_NOT_FOUND, "[E_KEY_NOT_FOUND] entry was not found.");
1267
1268         SetLastResult(E_SUCCESS);
1269         return entryIndex;
1270 }
1271
1272 String
1273 _RegistryCore::GetEntryName(int sectionIndex, int entryIndex)
1274 {
1275         _RegistrySection* pRegSection = null;
1276         _RegistryEntry* pRegEntry = null;
1277         int listSize = 0;
1278         int tmpIndex = -1;
1279         String empty;
1280
1281         SysAssertf(_constructed == true, "Not yet constructed. Construct() should be called before use.\n");
1282         SysTryReturn(NID_IO, sectionIndex >= 0, empty, E_INVALID_ARG, "[E_INVALID_ARG]sectionIndex < 0.");
1283         SysTryReturn(NID_IO, entryIndex >= 0, empty, E_INVALID_ARG, "[E_INVALID_ARG]entryIndex < 0.");
1284
1285         listSize = _sectionList.GetCount();
1286         SysTryReturn(NID_IO, listSize > 0, empty, E_SECTION_NOT_FOUND,
1287                            "[E_SECTION_NOT_FOUND]Registry section list is empty.");
1288         SysTryReturn(NID_IO, sectionIndex < listSize, empty, E_SECTION_NOT_FOUND,
1289                            "[E_SECTION_NOT_FOUND]sectionIndex >= listSize.");
1290
1291         pRegSection = (_RegistrySection*) GetSectionByIndex(sectionIndex);
1292         SysTryReturn(NID_IO, pRegSection != null, empty, E_SECTION_NOT_FOUND,
1293                            "[E_SECTION_NOT_FOUND] Section at index (%d) not found.", sectionIndex);
1294
1295         // read the entries for this section
1296         unique_ptr<IEnumerator> pEntryEnum(pRegSection->__entryList.GetEnumeratorN());
1297         SysTryReturn(NID_IO, pEntryEnum != null, empty, GetLastResult(), "[%s] Entry list is empty.",
1298                         GetErrorMessage(GetLastResult()));
1299
1300         tmpIndex = entryIndex;
1301         while (pEntryEnum->MoveNext() == E_SUCCESS)
1302         {
1303                 if (tmpIndex == 0)
1304                 {
1305                         pRegEntry = dynamic_cast <_RegistryEntry*>(pEntryEnum->GetCurrent());
1306                         SysTryReturn(NID_IO, pRegEntry != null, empty, GetLastResult(), "[%s] Propagated.",
1307                                            GetErrorMessage(GetLastResult()));
1308
1309                         break;
1310                 }
1311                 tmpIndex--;
1312         }
1313
1314         SysTryReturn(NID_IO, pRegEntry != null, empty, E_KEY_NOT_FOUND, "[E_KEY_NOT_FOUND] entry was not found.");
1315
1316         SetLastResult(E_SUCCESS);
1317         return pRegEntry->entryName;
1318 }
1319
1320 void
1321 _RegistryCore::GetEntryValue(int sectionIndex, int entryIndex, _RegValueType type, void* pValue, int* pSize)
1322 {
1323         _RegistrySection* pRegSection = null;
1324         _RegistryEntry* pRegEntry = null;
1325         result r = E_SUCCESS;
1326         int listSize = 0;
1327         int tmpEntryIndex = -1;
1328         int entryListSize = 0;
1329         String strValueEncoded;
1330
1331         SysAssertf(_constructed == true, "Not yet constructed. Construct() should be called before use.\n");
1332         SysTryReturnVoidResult(NID_IO, sectionIndex >= 0, E_INVALID_ARG, "[E_INVALID_ARG]sectionIndex < 0.");
1333         SysTryReturnVoidResult(NID_IO, type >= 0 && type <= REG_VALUE_TYPE_MAX, E_INVALID_ARG,
1334                            "[E_INVALID_ARG] invalid registry type.");
1335         SysTryReturnVoidResult(NID_IO, pValue != null, E_INVALID_ARG, "[E_INVALID_ARG]pValue is null.");
1336         SysTryReturnVoidResult(NID_IO, pSize != null, E_INVALID_ARG, "[E_INVALID_ARG]pSize is null.");
1337         SysTryReturnVoidResult(NID_IO, *pSize > 0, E_INVALID_ARG, "[E_INVALID_ARG] *pSize < 0.");
1338
1339         listSize = _sectionList.GetCount();
1340         SysTryReturnVoidResult(NID_IO, listSize > 0, E_SECTION_NOT_FOUND,
1341                            "[E_SECTION_NOT_FOUND]Registry section list is empty.");
1342         SysTryReturnVoidResult(NID_IO, sectionIndex < listSize, E_SECTION_NOT_FOUND,
1343                            "[E_SECTION_NOT_FOUND]sectionIndex >= listSize.");
1344
1345         pRegSection = (_RegistrySection*) GetSectionByIndex(sectionIndex);
1346         SysTryReturnVoidResult(NID_IO, pRegSection != null, E_SECTION_NOT_FOUND,
1347                            "[E_SECTION_NOT_FOUND] section at index (%d) is not available.", sectionIndex);
1348
1349         entryListSize = pRegSection->__entryList.GetCount();
1350         SysTryReturnVoidResult(NID_IO, entryListSize > 0, E_KEY_NOT_FOUND, "[E_KEY_NOT_FOUND]Entry list is empty.");
1351         SysTryReturnVoidResult(NID_IO, entryIndex < entryListSize, E_KEY_NOT_FOUND, "[E_KEY_NOT_FOUND]Entry not found.");
1352
1353         // read the entries for this section
1354         unique_ptr< IEnumerator > pEntryEnum(pRegSection->__entryList.GetEnumeratorN());
1355         SysTryReturnVoidResult(NID_IO, pEntryEnum != null, E_OBJ_NOT_FOUND, "[E_OBJ_NOT_FOUND]Entry list is empty.");
1356
1357         tmpEntryIndex = entryIndex;
1358         while (pEntryEnum->MoveNext() == E_SUCCESS)
1359         {
1360                 if (entryIndex == 0)
1361                 {
1362                         pRegEntry = dynamic_cast <_RegistryEntry*>(pEntryEnum->GetCurrent());
1363                         SysTryReturnVoidResult(NID_IO, pRegEntry != null, GetLastResult(), "[%s] Propagated.",
1364                                            GetErrorMessage(GetLastResult()));
1365
1366                         break;
1367                 }
1368                 entryIndex--;
1369
1370         }
1371
1372         SysTryReturnVoidResult(NID_IO, pRegEntry != null, E_KEY_NOT_FOUND,
1373                            "[E_KEY_NOT_FOUND] Entry was not found.");
1374
1375         strValueEncoded = pRegEntry->entryValue;
1376
1377         DecodeData(strValueEncoded, type, pValue, pSize);
1378         r = GetLastResult();
1379         SysTryReturnVoidResult(NID_IO, !IsFailed(r), E_PARSING_FAILED, "[%s] Propagated.", GetErrorMessage(r));
1380
1381         SetLastResult(E_SUCCESS);
1382         return;
1383 }
1384
1385 String
1386 _RegistryCore::GetSectionName(int sectionIndex)
1387 {
1388         _RegistrySection* pRegSection = null;
1389         result r = E_SUCCESS;
1390         int listSize = 0;
1391         String sectionName("");
1392
1393         SysAssertf(_constructed == true, "Not yet constructed. Construct() should be called before use.\n");
1394         SysTryReturn(NID_IO, sectionIndex >= 0, sectionName, E_INVALID_ARG, "[E_INVALID_ARG]sectionIndex < 0.");
1395
1396         listSize = _sectionList.GetCount();
1397         SysTryReturn(NID_IO, listSize > 0, sectionName, E_SECTION_NOT_FOUND,
1398                            "[E_SECTION_NOT_FOUND]Registry section list is empty.");
1399         SysTryReturn(NID_IO, sectionIndex < listSize, sectionName, E_SECTION_NOT_FOUND,
1400                            "[E_SECTION_NOT_FOUND]sectionIndex >= listSize.");
1401
1402         pRegSection = (_RegistrySection*) GetSectionByIndex(sectionIndex);
1403         SysTryReturn(NID_IO, pRegSection != null, sectionName, E_SECTION_NOT_FOUND,
1404                            "[E_SECTION_NOT_FOUND] sectionIndex is not available.");
1405
1406         r = GetLastResult();
1407         SysTryReturn(NID_IO, !IsFailed(r), sectionName, r, "[%s] Propagated.", GetErrorMessage(r));
1408
1409         SetLastResult(E_SUCCESS);
1410         return pRegSection->__sectionName;
1411 }
1412
1413 void*
1414 _RegistryCore::GetSectionByIndex(int sectionIndex)
1415 {
1416         _RegistrySection* pRegSection = null;
1417         int index = sectionIndex;
1418
1419         // Get section information
1420         unique_ptr<IEnumerator> pEnum(_sectionList.GetEnumeratorN());
1421         SysTryReturn(NID_IO, pEnum != null, null, GetLastResult(),
1422                            "[%s] section list is empty.", GetErrorMessage(GetLastResult()));
1423
1424         while (pEnum->MoveNext() == E_SUCCESS)
1425         {
1426                 if (index == 0)
1427                 {
1428                         pRegSection = dynamic_cast< _RegistrySection* >(pEnum->GetCurrent());
1429                         SysTryReturn(NID_IO, pRegSection != null, null, GetLastResult(), "[%s] Propagated.",
1430                                            GetErrorMessage(GetLastResult()));
1431                         break;
1432                 }
1433                 index--;
1434
1435         }
1436
1437         SysTryReturn(NID_IO, pRegSection != null, null, E_SECTION_NOT_FOUND,
1438                            "[E_SECTION_NOT_FOUND] Section was not found.");
1439
1440         SetLastResult(E_SUCCESS);
1441
1442         return pRegSection;
1443 }
1444
1445 void
1446 _RegistryCore::DecodeData(const String& strValueEncoded, _RegValueType type, void* pValue, int* pSize)
1447 {
1448         SysAssert(strValueEncoded.GetLength() > 0);
1449         SysAssert(pValue);
1450         SysAssert(pSize);
1451         SysAssert(pSize && *pSize > 0);
1452
1453         SysTryReturnVoidResult(NID_IO, pValue != null, E_INVALID_ARG, "[E_INVALID_ARG] Invalid argument.");
1454         SysTryReturnVoidResult(NID_IO, pSize != null, E_INVALID_ARG, "[E_INVALID_ARG] Invalid argument.");
1455
1456         switch (type)
1457         {
1458         case REG_VALUE_TYPE_INT: // (-2147483647 - 1) ~ 2147483647
1459         {
1460                 int retIntVal = 0;
1461                 result r = E_SUCCESS;
1462
1463                 if (*pSize != sizeof(int))
1464                 {
1465                         SetLastResult(E_INVALID_ARG);
1466                         return;
1467                 }
1468
1469                 r = Integer::Parse(strValueEncoded, retIntVal);
1470                 SysTryReturnVoidResult(NID_IO, !IsFailed(r), E_PARSING_FAILED, "[%s] Propagated.", GetErrorMessage(r));
1471
1472                 *(int*) pValue = retIntVal;
1473                 break;
1474         }
1475
1476         case REG_VALUE_TYPE_REAL:  // Holds signed IEEE 64-bit (8-byte) double-precision floating-point numbers
1477                                         // ranging in value from -1.79769313486231570E+308 through -4.94065645841246544E-324
1478                                         // for negative values and from 4.94065645841246544E-324 through 1.79769313486231570E+308
1479                                         // for positive values.
1480         {
1481                 double retDoubleVal = 0;
1482                 result r = E_SUCCESS;
1483
1484                 if (*pSize != sizeof(double))
1485                 {
1486                         SetLastResult(E_INVALID_ARG);
1487                         return;
1488                 }
1489
1490                 r = Double::Parse(strValueEncoded, retDoubleVal);
1491                 SysTryReturnVoidResult(NID_IO, !IsFailed(r), E_PARSING_FAILED, "[%s] Propagated.", GetErrorMessage(r));
1492
1493                 *(double*) pValue = retDoubleVal;
1494                 break;
1495         }
1496
1497         case REG_VALUE_TYPE_STRING:
1498         {
1499 //              if(*pSize != sizeof(String))
1500 //              {
1501 //                      SetLastResult(E_INVALID_ARG);
1502 //                      return;
1503 //              }
1504                 *(String*) pValue = strValueEncoded;
1505                 break;
1506         }
1507
1508         case REG_VALUE_TYPE_BINARY:
1509         {
1510                 SetLastResult(E_PARSING_FAILED);
1511                 return;
1512         }
1513
1514         case REG_VALUE_TYPE_UUID:
1515         {
1516                 UuId retUuIdVal;
1517                 result r = E_SUCCESS;
1518
1519                 r = UuId::Parse(strValueEncoded, retUuIdVal);
1520                 SysTryReturnVoidResult(NID_IO, !IsFailed(r), E_PARSING_FAILED, "[%s] Propagated.", GetErrorMessage(r));
1521
1522                 *(UuId*) pValue = retUuIdVal;
1523                 break;
1524         }
1525
1526         case REG_VALUE_TYPE_UUIDSET:
1527         {
1528                 SetLastResult(E_PARSING_FAILED);
1529                 return;
1530         }
1531
1532         default:
1533                 SysAssert(0); // should not happen!
1534                 return;
1535         }
1536
1537         SetLastResult(E_SUCCESS);
1538         return;
1539 }
1540
1541 result
1542 _RegistryCore::AddSection(LinkedList& sectionList, const String& sectionName)
1543 {
1544         result r = E_SUCCESS;
1545         bool sectionFound = false;
1546
1547         // Get section information
1548         unique_ptr<IEnumerator> pEnum(sectionList.GetEnumeratorN());
1549         if (pEnum == null)
1550         {
1551                 return GetLastResult();
1552         }
1553
1554         while (pEnum->MoveNext() == E_SUCCESS)
1555         {
1556                 _RegistrySection* pRegSection = dynamic_cast <_RegistrySection*>(pEnum->GetCurrent());
1557                 SysTryReturn(NID_IO, pRegSection != null, GetLastResult(), GetLastResult(), "[%s] Propagated.",
1558                                    GetErrorMessage(GetLastResult()));
1559
1560                 if (pRegSection->__sectionName == sectionName)
1561                 {
1562                         sectionFound = true;
1563                         break;
1564                 }
1565         }
1566
1567         if (sectionFound == true)
1568         {
1569                 return E_SECTION_ALREADY_EXIST;
1570         }
1571
1572         // create a key with section name
1573         unique_ptr<_RegistrySection> pRegSection(new (std::nothrow) _RegistrySection());
1574
1575         SysTryReturnResult(NID_IO, pRegSection != null, E_OUT_OF_MEMORY,
1576                            "The memory is insufficient.");
1577
1578         pRegSection->__sectionName = sectionName;
1579
1580         // add new section and section-entry map
1581         r = sectionList.Add(*(pRegSection.release()));
1582         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagated.", GetErrorMessage(r));
1583
1584         return E_SUCCESS;
1585 }
1586
1587 result
1588 _RegistryCore::AddValue(LinkedList& sectionList, const String& sectionName, const String& entryName, const String& valStr)
1589 {
1590         result r = E_SUCCESS;
1591         bool sectionFound = false;
1592         bool entryFound = false;
1593         _RegistrySection* pRegSection = null;
1594
1595         // Get section information
1596         unique_ptr<IEnumerator> pEnum(sectionList.GetEnumeratorN());
1597         if (pEnum == null)
1598         {
1599                 return GetLastResult();
1600         }
1601
1602         while (pEnum->MoveNext() == E_SUCCESS)
1603         {
1604                 pRegSection = dynamic_cast <_RegistrySection*>(pEnum->GetCurrent());
1605                 SysTryReturn(NID_IO, pRegSection != null, GetLastResult(), GetLastResult(), "[%s] Propagated.",
1606                                    GetErrorMessage(GetLastResult()));
1607
1608                 if (pRegSection->__sectionName == sectionName)
1609                 {
1610                         sectionFound = true;
1611                         break;
1612                 }
1613         }
1614
1615         if (sectionFound == false)
1616         {
1617                 return E_SECTION_NOT_FOUND;
1618         }
1619
1620         pEnum.reset(pRegSection->__entryList.GetEnumeratorN());
1621         if (pEnum == null)
1622         {
1623                 return GetLastResult();
1624         }
1625
1626         while (pEnum->MoveNext() == E_SUCCESS)
1627         {
1628                 _RegistryEntry* pRegEntry = dynamic_cast <_RegistryEntry*>(pEnum->GetCurrent());
1629                 SysTryReturn(NID_IO, pRegEntry != null, GetLastResult(), GetLastResult(), "[%s] Propagated.",
1630                                    GetErrorMessage(GetLastResult()));
1631
1632                 if (pRegEntry->entryName == entryName)
1633                 {
1634                         entryFound = true;
1635                         break;
1636                 }
1637         }
1638
1639         if (entryFound == true)
1640         {
1641                 return E_KEY_ALREADY_EXIST;
1642         }
1643
1644         unique_ptr<_RegistryEntry> pRegEntry(new (std::nothrow) _RegistryEntry());
1645         SysTryReturnResult(NID_IO, pRegEntry != null, E_OUT_OF_MEMORY,
1646                         "The memory is insufficient.");
1647
1648         pRegEntry->entryName = entryName;
1649         pRegEntry->entryValue = valStr;
1650
1651         r = pRegSection->__entryList.Add(*(pRegEntry.release()));
1652         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagated.", GetErrorMessage(r));
1653
1654         return E_SUCCESS;
1655 }
1656
1657 bool
1658 _RegistryCore::CheckSectionName(char* pSectionName)
1659 {
1660         char* pTemp = null;
1661         int length = 0;
1662         char* pFrom = null;
1663         char* pTo = null;
1664
1665         if (pSectionName == null)
1666         {
1667                 return false;
1668         }
1669
1670         pFrom = pSectionName;
1671         length = strlen(pSectionName);
1672         pTo = pSectionName + (length - 1);
1673
1674         if (!pFrom || !pTo || pFrom > pTo)
1675         {
1676                 return false;
1677         }
1678
1679         for (pTemp = pFrom; pTemp <= pTo; pTemp++)
1680         {
1681                 if (*pTemp == '\0' || *pTemp == '\n' || *pTemp == '#' || *pTemp == '=')
1682                 {
1683                         return false;
1684                 }
1685         }
1686
1687         return true;
1688 }
1689
1690 bool
1691 _RegistryCore::CheckEntryName(char* pEntryName)
1692 {
1693         char* pTemp = null;
1694         int length = 0;
1695         char* pFrom = null;
1696         char* pTo = null;
1697
1698         if (pEntryName == null)
1699         {
1700                 return false;
1701         }
1702
1703         pFrom = pEntryName;
1704         length = strlen(pEntryName);
1705         pTo = pEntryName + (length - 1);
1706
1707         if (!pFrom || !pTo || pFrom > pTo)
1708         {
1709                 return false;
1710         }
1711
1712         for (pTemp = pFrom; pTemp <= pTo; pTemp++)
1713         {
1714                 if (*pTemp == '\0' || *pTemp == '\n' || *pTemp == '#' || *pTemp == '=')
1715                 {
1716                         return false;
1717                 }
1718         }
1719
1720         return true;
1721 }
1722
1723 bool
1724 _RegistryCore::CheckEntryValue(char* pEntryVal)
1725 {
1726         char* pTemp = null;
1727         int length = 0;
1728         char* pFrom = null;
1729         char* pTo = null;
1730
1731         if (pEntryVal == null)
1732         {
1733                 return false;
1734         }
1735
1736         pFrom = pEntryVal;
1737         length = strlen(pEntryVal);
1738         pTo = pEntryVal + (length - 1);
1739
1740         if (!pFrom || !pTo || pFrom > pTo)
1741         {
1742                 return false;
1743         }
1744
1745         for (pTemp = pFrom; pTemp <= pTo; pTemp++)
1746         {
1747                 if (*pTemp == '\0' || *pTemp == '\n')
1748                 {
1749                         return false;
1750                 }
1751         }
1752
1753         return true;
1754 }
1755
1756 result
1757 _RegistryCore::ConvertToSecureRegistry(const String& plainRegPath, const String& secureRegPath, const ByteBuffer* pKey)
1758 {
1759         result  r = E_SUCCESS;
1760
1761         if (File::IsFileExist(secureRegPath))
1762         {
1763                 r = GetLastResult();
1764                 if (r == E_SUCCESS)
1765                 {
1766                         r = E_FILE_ALREADY_EXIST;
1767                         SysLog(NID_IO, "[E_FILE_ALREADY_EXIST] The secure registry already exists.");
1768                 }
1769                 else
1770                 {
1771                         SysLog(NID_IO, "[%s]Propagated.", GetErrorMessage(r));
1772                 }
1773                 return r;
1774         }
1775
1776         unique_ptr<_NormalRegistry> pNormalReg(new (std::nothrow) _NormalRegistry());
1777         SysTryReturnResult(NID_IO, pNormalReg != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
1778
1779         r = pNormalReg->Load(plainRegPath, "r");
1780         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagated.", GetErrorMessage(r));
1781
1782         unique_ptr<_SecureRegistry> pSecureReg(new (std::nothrow) _SecureRegistry());
1783         SysTryReturnResult(NID_IO, pSecureReg != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
1784
1785         r = pSecureReg->Construct(secureRegPath, "w+", pKey);
1786         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagated.", GetErrorMessage(r));
1787
1788         if (pNormalReg->_pBuffer != null && pNormalReg->_length > 0)
1789         {
1790                 pSecureReg->_pBuffer = pNormalReg->_pBuffer;
1791                 pSecureReg->_length = pNormalReg->_length;
1792
1793                 pNormalReg->_pBuffer = null;
1794                 pNormalReg->_length = 0;
1795
1796                 r = pSecureReg->Parse();
1797                 SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagated.", GetErrorMessage(r));
1798         }
1799
1800         r = pSecureReg->Flush();
1801         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagated.", GetErrorMessage(r));
1802
1803         return E_SUCCESS;
1804 }
1805
1806 FileLock*
1807 _RegistryCore::LockN(FileLockType lockType)
1808 {
1809         SysAssertf(_constructed == true && __pFileImpl != null, "Not yet constructed. Construct() should be called before use.\n");
1810         return __pFileImpl->LockN(lockType);
1811 }
1812
1813 FileLock*
1814 _RegistryCore::TryToLockN(FileLockType lockType)
1815 {
1816         SysAssertf(_constructed == true && __pFileImpl != null, "Not yet constructed. Construct() should be called before use.\n");
1817         return __pFileImpl->TryToLockN(lockType);
1818 }
1819
1820 }} // Tizen::Io
1821