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