4581a51d6d589eeb83c7690f39214882e6be98b3
[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 }
102
103 bool
104 _RegistryCore::VerifyRegistryOpenMode(const char* pOpenMode)
105 {
106         if (pOpenMode == null)
107         {
108                 SysLog(NID_IO, "[E_INVALID_ARG] The specified openMode is null.");
109                 return false;
110         }
111
112         if (strlen(pOpenMode) > _MAX_REG_OPENMODE_LENGTH)
113         {
114                 SysLog(NID_IO, "[E_INVALID_ARG] The specified openMode (%s) is invalid.", pOpenMode);
115                 return false;
116         }
117
118         switch (pOpenMode[0])
119         {
120         case 'r':
121                 _read = true;
122                 break;
123         case 'w':
124                 _write = true;
125                 _truncate = true;
126                 break;
127         case 'a':
128                 _write = true;
129                 _append = true;
130                 break;
131         default:
132                 SysLog(NID_IO, "[E_INVALID_ARG] The specified openMode (%s) is invalid.", pOpenMode);
133                 return false;
134         }
135
136         switch (pOpenMode[1])
137         {
138         case '\0':
139                 break;
140         case '+':
141                 if (pOpenMode[2] == '\0')
142                 {
143                         _read = true;
144                         _write = true;
145                         break;
146                 }
147                 else
148                 {
149                         SysLog(NID_IO, "[E_INVALID_ARG] The specified openMode (%s) is invalid.", pOpenMode);
150                         return false;
151                 }
152         default:
153                 SysLog(NID_IO, "[E_INVALID_ARG] The specified openMode (%s) is invalid.", pOpenMode);
154                 return false;
155         }
156
157         return true;
158 }
159
160 result
161 _RegistryCore::Parse(void)
162 {
163         result r = E_SUCCESS;
164         wchar_t ch = '\0';
165         bool sectionFound = false;
166         String sectionName;
167         int length = 0;
168         unique_ptr<char[]> pEntryName(null);
169         unique_ptr<char[]> pEntryValue(null);
170         int firstTokenPos = 0;
171         String line;
172
173         if (_pBuffer == null)
174         {
175                 SysLog(NID_IO, "The buffer is empty.");
176                 return E_SUCCESS;
177         }
178
179         String inputStr = String((char*)_pBuffer);
180         StringTokenizer lineTok(inputStr, L"\n");
181
182         r = lineTok.GetNextToken(line);
183
184         while (r == E_SUCCESS)
185         {
186                 // skip empty lines
187                 if (line.GetLength() == 0)
188                 {
189                         r = lineTok.GetNextToken(line);
190                         continue;
191                 }
192
193                 // find registry section marker
194                 line.GetCharAt(0, ch);
195                 if (ch == _REGISTRY_SECTION_MARKER_CHAR)
196                 {
197                         sectionFound = true;
198
199                         // skip '#' and "\n' at the end
200                         r = line.SubString(1, line.GetLength() - 1, sectionName);
201                         SysTryCatch(NID_IO, !IsFailed(r), , r, "[%s] Propagated.", GetErrorMessage(r));
202
203                         // if End of the document follows section name without newline character.
204                         sectionName.GetCharAt(sectionName.GetLength() - 1, ch);
205                         if (ch == L'\n')
206                         {
207                                 sectionName.SetLength(sectionName.GetLength() - 1); //Remove '\n'
208                         }
209
210                         // for compatibility check if line contains  '\r' at the end
211                         sectionName.GetCharAt(sectionName.GetLength() - 1, ch);
212                         if (ch == L'\r')
213                         {
214                                 sectionName.SetLength(sectionName.GetLength() - 1); //Remove '\r'
215                         }
216
217                         //TODO: check if remaining data in sectionName is valid or not
218                         //after removing '#', '\n', and '\r', sectionName should contain at least 1 valid character
219                         SysTryCatch(NID_IO,
220                                            sectionName.GetLength() > 0, r = E_PARSING_FAILED, E_PARSING_FAILED,
221                                            "[E_PARSING_FAILED] Section length cannot be <2.");
222
223                         unique_ptr<char[]> pSectionName(_StringConverter::CopyToCharArrayN(sectionName));
224                         SysTryCatch(NID_IO, pSectionName != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
225                                            "[E_OUT_OF_MEMORY] The memory is insufficient.");
226
227                         if (!_RegistryCore::CheckSectionName(pSectionName.get()))
228                         {
229                                 SysTryCatch(NID_IO, false, r = E_PARSING_FAILED, E_PARSING_FAILED,
230                                                    "[E_PARSING_FAILED] Section name could not be parsed.");
231                         }
232
233                         r = _RegistryCore::AddSection(_sectionList, sectionName);
234                         SysTryCatch(NID_IO, !IsFailed(r), , r, "[%s] Propagated.", GetErrorMessage(r));
235                 }
236                 else    // not a section.. but may belongs to a section (entry)
237                 {
238                         // ignores blank lines
239                         line.GetCharAt(0, ch);
240                         if ((ch == L'\n') || (ch == L'\r'))
241                         {
242                                 r = lineTok.GetNextToken(line);
243                                 continue;
244                         }
245
246                         //TODO
247                         // Need to check for tabs, spaces in the beginning of each line
248
249                         // if no section found till now.. ignore
250                         if (sectionFound == false)
251                         {
252                                 r = lineTok.GetNextToken(line);
253                                 continue;
254                         }
255
256                         // if End of the document follows entry value without newline character.
257                         line.GetCharAt(line.GetLength() - 1, ch);
258                         if (ch == L'\n')
259                         {
260                                 line.SetLength(line.GetLength() - 1); //Remove '\n'
261                         }
262
263                         line.GetCharAt(line.GetLength() - 1, ch);
264                         if (ch == L'\r')
265                         {
266                                 line.SetLength(line.GetLength() - 1); //Remove '\r'
267                         }
268
269                         String entryName("");
270                         String entryVal("");
271
272                         // we will have sectionitem=value (or) sectionitem= (or) sectionitem
273                         // as our string. Break this into entry and value
274                         StringTokenizer strTok(line, L"=");
275
276                         // extract entry name
277                         if (strTok.HasMoreTokens())
278                         {
279                                 line.IndexOf(L'=', 0, firstTokenPos); // position of first occurance of '=' in a line
280                                 if (firstTokenPos == 0)
281                                 {
282                                         // entryName should not be empty. i.e., "=value"  or just '=' is invalid case
283                                         SysTryCatch(NID_IO, false, r = E_PARSING_FAILED, E_PARSING_FAILED,
284                                                            "[E_PARSING_FAILED] Entry name cannot be empty.");
285                                 }
286                                 else
287                                 {
288                                         strTok.GetNextToken(entryName);
289                                 }
290                         }
291                         else // missing '=' in  entry line or entry line does not seem to contain "xxx=xxx" format
292                         {
293                                 SysTryCatch(NID_IO, false, r = E_PARSING_FAILED, E_PARSING_FAILED, "[E_PARSING_FAILED] invalid entry Line found.");
294                         }
295
296                         // check if entry name contains invalid chars
297                         pEntryName.reset(_StringConverter::CopyToCharArrayN(entryName));
298                         SysTryCatch(NID_IO, pEntryName, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
299                                            "[E_OUT_OF_MEMORY] The memory is insufficient.");
300
301                         if (!_RegistryCore::CheckEntryName(pEntryName.get()))
302                         {
303                                 SysTryCatch(NID_IO, false, r = E_PARSING_FAILED, E_PARSING_FAILED,
304                                                    "[E_PARSING_FAILED] Entry name could not be parsed.");
305                         }
306
307                         line.SubString(firstTokenPos + 1, entryVal); // extract entry value
308
309                         // check if entry value contains invalid chars
310                         pEntryValue.reset(_StringConverter::CopyToCharArrayN(entryVal));
311                         SysTryCatch(NID_IO, pEntryValue, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
312                                            "[E_OUT_OF_MEMORY] The memory is insufficient.");
313
314                         length = strlen(pEntryValue.get());
315                         if (length > 0)
316                         {
317                                 if (!_RegistryCore::CheckEntryValue(pEntryValue.get()))
318                                 {
319                                         SysTryCatch(NID_IO, false, r = E_PARSING_FAILED, E_PARSING_FAILED,
320                                                            "[E_PARSING_FAILED] Entry value could not be parsed.");
321                                 }
322                         }
323
324                         // add the entry and value
325                         r = _RegistryCore::AddValue(_sectionList, sectionName, entryName, entryVal);
326                         SysTryCatch(NID_IO, !IsFailed(r), , r, "[%s] Propagated.", GetErrorMessage(r));
327                 }
328                 r = lineTok.GetNextToken(line);
329         } // while()
330
331         if (r == E_OUT_OF_RANGE)
332         {
333                 r = E_SUCCESS;
334         }
335
336         // fall through
337 CATCH:
338
339         if (r == E_PARSING_FAILED && Tizen::App::_AppInfo::IsOspCompat() == false)
340         {
341                 r = E_INVALID_FORMAT;
342         }
343
344         SysLog(NID_IO, "[%s] exception occurred.", GetErrorMessage(r));
345         return r;
346 }
347
348 result
349 _RegistryCore::Load(const String& regPath, const char* pOpenMode)
350 {
351         result r = E_SUCCESS;
352         delete[] _pBuffer; //clear existing buffer
353         _pBuffer = null;
354         _length = 0;
355
356         // open registry file
357         unique_ptr<_FileImpl> pFileImpl(new (std::nothrow) _FileImpl());
358         SysTryReturnResult(NID_IO, pFileImpl != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
359
360         r = pFileImpl->Construct(regPath, pOpenMode, null);
361         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Constructing the file has failed.", GetErrorMessage(r));
362
363         // reset the section list to be sure that its empty
364         _sectionList.RemoveAll(true);
365
366         if (_truncate == false)
367         {
368                 // load the registry file
369                 r = pFileImpl->ReadN((char**)&_pBuffer, _length);
370                 if (_length > 0)
371                 {
372                         _length--;
373                 }
374         }
375
376         __pFileImpl = pFileImpl.release();
377
378         return r;
379 }
380
381 result
382 _RegistryCore::AddSection(const String& sectionName)
383 {
384         SysAssertf(_constructed == true, "Not yet constructed. Construct() should be called before use.\n");
385
386         result r = E_SUCCESS;
387         bool sectionFound = false;
388
389         // Get section information
390         unique_ptr<IEnumerator> pEnum(_sectionList.GetEnumeratorN());
391         if (pEnum == null)
392         {
393                 return GetLastResult();
394         }
395
396         while (pEnum->MoveNext() == E_SUCCESS)
397         {
398                 _RegistrySection* pRegSection = dynamic_cast <_RegistrySection*>(pEnum->GetCurrent());
399                 SysTryReturn(NID_IO, pRegSection != null, GetLastResult(), GetLastResult(), "[%s] Propagated.",
400                                    GetErrorMessage(GetLastResult()));
401
402                 if (pRegSection->__sectionName == sectionName)
403                 {
404                         sectionFound = true;
405                         break;
406                 }
407         }
408
409         if (sectionFound == true)
410         {
411                 return E_SECTION_ALREADY_EXIST;
412         }
413
414         // create a key with section name
415         unique_ptr<_RegistrySection> pRegSection(new (std::nothrow) _RegistrySection());
416         SysTryReturnResult(NID_IO, pRegSection != null, E_OUT_OF_MEMORY,
417                            "The memory is insufficient.");
418
419         pRegSection->__sectionName = sectionName;
420
421         // add new section and section-entry map
422         r = _sectionList.Add(*(pRegSection.release()));
423         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagated.", GetErrorMessage(r));
424
425         _update = true;
426         return E_SUCCESS;
427 }
428
429 result
430 _RegistryCore::RemoveSection(const String& sectionName)
431 {
432         SysAssertf(_constructed == true, "Not yet constructed. Construct() should be called before use.\n");
433
434         result r = E_SUCCESS;
435         _RegistrySection* pRegSection = null;
436         bool sectionFound = false;
437
438         if (_sectionList.GetCount() == 0)
439         {
440                 return E_SECTION_NOT_FOUND;
441         }
442
443         // Get section information
444         unique_ptr<IEnumerator> pEnum(_sectionList.GetEnumeratorN());
445         if (pEnum == null)
446         {
447                 return GetLastResult();
448         }
449
450         while (pEnum->MoveNext() == E_SUCCESS)
451         {
452                 pRegSection = dynamic_cast< _RegistrySection* >(pEnum->GetCurrent());
453                 SysTryReturn(NID_IO, pRegSection != null, GetLastResult(), GetLastResult(), "[%s] Propagating.",
454                                    GetErrorMessage(GetLastResult()));
455
456                 if (pRegSection->__sectionName == sectionName)
457                 {
458                         sectionFound = true;
459                         break;
460                 }
461         }
462
463         if (sectionFound == false)
464         {
465                 return E_SECTION_NOT_FOUND;
466         }
467
468         r = _sectionList.Remove(*pRegSection, true);
469         SysTryReturnResult(NID_IO, !IsFailed(r), E_IO, "system error");
470
471         _update = true;
472         return E_SUCCESS;
473 }
474
475 result
476 _RegistryCore::GetSectionListN(IList** pRetList)
477 {
478         result r = E_SUCCESS;
479         unique_ptr<IEnumerator> pEnum(null);
480         _RegistrySection* pSection = null;
481
482         SysAssertf(_constructed == true, "Not yet constructed. Construct() should be called before use.\n");
483         SysTryReturnResult(NID_IO, pRetList != null, E_INVALID_ARG, "pList cannot be null.");
484
485         // construct an array list to be returned
486         unique_ptr<ArrayList, AllElementsDeleter> pSectionList(new (std::nothrow) ArrayList());
487         SysTryReturnResult(NID_IO, pSectionList != null, E_OUT_OF_MEMORY,
488                            "The memory is insufficient.");
489
490         r = pSectionList->Construct();
491         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagated.", GetErrorMessage(r));
492
493         // if no sectons, return empty list
494         if (_sectionList.GetCount() == 0)
495         {
496                 *pRetList = pSectionList.release();
497                 return E_SUCCESS;
498         }
499
500         // copy from class section list to the new list and return
501         pEnum.reset(_sectionList.GetEnumeratorN());
502         SysTryReturn(NID_IO, pEnum != null, GetLastResult(), GetLastResult(), "[%s] Section list is empty.", GetErrorMessage(GetLastResult()));
503
504         while (pEnum->MoveNext() == E_SUCCESS)
505         {
506                 pSection = dynamic_cast <_RegistrySection*>(pEnum->GetCurrent());
507                 SysTryReturn(NID_IO, pSection != null, GetLastResult(), GetLastResult(), "[%s] Propagated.",
508                                    GetErrorMessage(GetLastResult()));
509
510                 unique_ptr<String> pSectionName(new (std::nothrow) String(pSection->__sectionName));
511                 SysTryReturnResult(NID_IO, pSectionName != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
512
513                 r = pSectionList->Add(*(pSectionName.release()));
514                 SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagated.", GetErrorMessage(r));
515         }
516
517         *pRetList = pSectionList.release();
518
519         return E_SUCCESS;
520 }
521
522 result
523 _RegistryCore::GetEntryList(const String& sectionName, Collection::HashMap& retMap)
524 {
525         result r = E_SUCCESS;
526         unique_ptr<IEnumerator> pEnum(null);
527         unique_ptr<String> pKeyEntryStr(null);
528         unique_ptr<String> pKeyValStr(null);
529         bool sectionFound = false;
530         _RegistrySection* pRegSection = null;
531         _RegistryEntry* pRegEntry = null;
532
533         SysAssertf(_constructed == true, "Not yet constructed. Construct() should be called before use.\n");
534
535         if (_sectionList.GetCount() == 0)
536         {
537                 return E_SECTION_NOT_FOUND;
538         }
539
540         // Get section information
541         pEnum.reset(_sectionList.GetEnumeratorN());
542         SysTryReturnResult(NID_IO, pEnum != null, E_SYSTEM, "Section list is empty.");
543
544         while (pEnum->MoveNext() == E_SUCCESS)
545         {
546                 pRegSection = dynamic_cast <_RegistrySection*>(pEnum->GetCurrent());
547                 SysTryReturn(NID_IO, pRegSection != null, GetLastResult(), GetLastResult(), "[%s] Propagated.",
548                                    GetErrorMessage(GetLastResult()));
549
550                 if (pRegSection->__sectionName == sectionName)
551                 {
552                         sectionFound = true;
553                         break;
554                 }
555         }
556
557         if (sectionFound == false)
558         {
559                 return E_SECTION_NOT_FOUND;
560         }
561
562         // copy from item list to the new list and return
563         pEnum.reset((pRegSection->__entryList).GetEnumeratorN());
564         SysTryReturn(NID_IO, pEnum != null, GetLastResult(), GetLastResult(), "[%s] Propagated.",
565                                            GetErrorMessage(GetLastResult()));
566
567         while (pEnum->MoveNext() == E_SUCCESS)
568         {
569                 pRegEntry = dynamic_cast <_RegistryEntry*>(pEnum->GetCurrent());
570                 SysTryReturn(NID_IO, pRegEntry != null, GetLastResult(), GetLastResult(), "[%s] Propagated.",
571                                    GetErrorMessage(GetLastResult()));
572
573                 pKeyEntryStr.reset(new (std::nothrow) String((pRegEntry->entryName)));
574                 SysTryCatch(NID_IO, pKeyEntryStr != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
575                                 "[E_OUT_OF_MEMORY] The memory is insufficient.");
576                 pKeyValStr.reset(new (std::nothrow) String((pRegEntry->entryValue)));
577                 SysTryCatch(NID_IO, pKeyValStr != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
578                                 "[E_OUT_OF_MEMORY] The memory is insufficient.");
579
580                 r = retMap.Add(*(pKeyEntryStr.release()), *(pKeyValStr.release()));
581                 SysTryCatch(NID_IO, !IsFailed(r), , r, "[%s] Propagated.", GetErrorMessage(r));
582         }
583
584         return E_SUCCESS;
585
586 CATCH:
587         retMap.RemoveAll(true);
588
589         return r;
590 }
591
592 result
593 _RegistryCore::GetEntryListN(const String& sectionName, HashMap** pRetList)
594 {
595         result r = E_SUCCESS;
596
597         SysAssertf(_constructed == true, "Not yet constructed. Construct() should be called before use.\n");
598         SysTryReturnResult(NID_IO, pRetList != null, E_INVALID_ARG, "pRetList cannot be null.");
599
600         // construct an array list to be returned
601         unique_ptr<HashMap, AllElementsDeleter> pEntryList(new (std::nothrow) HashMap());
602         SysTryReturnResult(NID_IO, pEntryList != null, E_OUT_OF_MEMORY,
603                         "The memory is insufficient.");
604         r = pEntryList->Construct();
605         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagated.", GetErrorMessage(r));
606         r = GetEntryList(sectionName, *(pEntryList.get()));
607         *pRetList = pEntryList.release();
608
609         return r;
610 }
611
612 IMap*
613 _RegistryCore::GetAllEntriesN(const String& sectionName)
614 {
615         result r = E_SUCCESS;
616         HashMap* pMap = null;
617
618         r = GetEntryListN(sectionName, &pMap);
619         SysTryCatch(NID_IO, !IsFailed(r), , r, "[%s] Propagated.", GetErrorMessage(r));
620
621         SetLastResult(E_SUCCESS);
622         return pMap;
623
624 CATCH:
625         SetLastResult(r);
626         return null;
627 }
628
629 IList*
630 _RegistryCore::GetAllEntryNamesN(const String& sectionName)
631 {
632         result r = E_SUCCESS;
633
634         unique_ptr<ArrayList, AllElementsDeleter> pEntryList(new (std::nothrow) ArrayList());
635         SysTryReturn(NID_IO, pEntryList != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
636
637         r = pEntryList->Construct();
638         SysTryReturn(NID_IO, !IsFailed(r), null, r, "[%s] Propagated.", GetErrorMessage(r));
639
640         unique_ptr<IMap, AllElementsDeleter> pMap(this->GetAllEntriesN(sectionName));
641         SysTryReturn(NID_IO, pMap != null, null, GetLastResult(), "[%s] Getting all entries was failed.",
642                         GetErrorMessage(GetLastResult()));
643
644         unique_ptr<IMapEnumerator> pMapEnum(pMap->GetMapEnumeratorN());
645         SysTryReturn(NID_IO, pMapEnum, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
646         while (pMapEnum->MoveNext() == E_SUCCESS)
647         {
648                 String* pKey = dynamic_cast< String* >(pMapEnum->GetKey());
649                 SysTryReturn(NID_IO, pKey != null, null, E_IO, "[E_OUT_OF_MEMORY] The system error occurred.");
650
651                 String* pEntryName = new (std::nothrow) String(*pKey);
652                 SysTryReturn(NID_IO, pEntryName != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
653
654                 r = pEntryList->Add(*pEntryName);
655                 SysTryReturn(NID_IO, !IsFailed(r), null, r, "[%s] Propagated.", GetErrorMessage(r));
656         }
657
658         SetLastResult(E_SUCCESS);
659         return pEntryList.release();
660 }
661
662 result
663 _RegistryCore::GetValue(const String& sectionName, const String& entryName, String& valStr)
664 {
665         bool sectionFound = false;
666         bool entryFound = false;
667         _RegistrySection* pRegSection = null;
668         _RegistryEntry* pRegEntry = null;
669
670         SysAssertf(_constructed == true, "Not yet constructed. Construct() should be called before use.\n");
671
672         if (_sectionList.GetCount() == 0)
673         {
674                 return E_SECTION_NOT_FOUND;
675         }
676
677         // Get section information
678         unique_ptr<IEnumerator> pEnum(_sectionList.GetEnumeratorN());
679         if (pEnum == null)
680         {
681                 return GetLastResult();
682         }
683
684         while (pEnum->MoveNext() == E_SUCCESS)
685         {
686                 pRegSection = dynamic_cast <_RegistrySection*>(pEnum->GetCurrent());
687                 SysTryReturn(NID_IO, pRegSection != null, GetLastResult(), GetLastResult(), "[%s] Propagated.",
688                                    GetErrorMessage(GetLastResult()));
689
690                 if (pRegSection->__sectionName == sectionName)
691                 {
692                         sectionFound = true;
693                         break;
694                 }
695         }
696
697         if (sectionFound == false)
698         {
699                 return E_SECTION_NOT_FOUND;
700         }
701
702         pEnum.reset(pRegSection->__entryList.GetEnumeratorN());
703         if (pEnum == null)
704         {
705                 return GetLastResult();
706         }
707
708         while (pEnum->MoveNext() == E_SUCCESS)
709         {
710                 pRegEntry = dynamic_cast <_RegistryEntry*>(pEnum->GetCurrent());
711                 SysTryReturn(NID_IO, pRegEntry != null, GetLastResult(), GetLastResult(), "[%s] Propagated.",
712                                    GetErrorMessage(GetLastResult()));
713
714                 if (pRegEntry->entryName == entryName)
715                 {
716                         valStr = pRegEntry->entryValue;
717                         entryFound = true;
718                         break;
719                 }
720         }
721
722         SysTryLog(NID_IO, entryFound, "Entry not found");
723
724         return((entryFound == true) ? E_SUCCESS : E_KEY_NOT_FOUND);
725 }
726
727 result
728 _RegistryCore::AddValue(const String& sectionName, const String& entryName, const String& valStr)
729 {
730         result r = E_SUCCESS;
731         bool sectionFound = false;
732         bool entryFound = false;
733         _RegistrySection* pRegSection = null;
734         int length = 0;
735
736         SysAssertf(_constructed == true, "Not yet constructed. Construct() should be called before use.\n");
737
738         // Get section information
739         unique_ptr<IEnumerator> pEnum(_sectionList.GetEnumeratorN());
740         if (pEnum == null)
741         {
742                 return GetLastResult();
743         }
744
745         while (pEnum->MoveNext() == E_SUCCESS)
746         {
747                 pRegSection = dynamic_cast <_RegistrySection*>(pEnum->GetCurrent());
748                 SysTryReturn(NID_IO, pRegSection != null, GetLastResult(), GetLastResult(), "[%s] Propagated.",
749                                    GetErrorMessage(GetLastResult()));
750
751                 if (pRegSection->__sectionName == sectionName)
752                 {
753                         sectionFound = true;
754                         break;
755                 }
756         }
757
758         if (sectionFound == false)
759         {
760                 return E_SECTION_NOT_FOUND;
761         }
762
763         pEnum.reset(pRegSection->__entryList.GetEnumeratorN());
764         if (pEnum == null)
765         {
766                 return GetLastResult();
767         }
768
769         while (pEnum->MoveNext() == E_SUCCESS)
770         {
771                 _RegistryEntry* pRegEntry = dynamic_cast <_RegistryEntry*>(pEnum->GetCurrent());
772                 SysTryReturn(NID_IO, pRegEntry != null, GetLastResult(), GetLastResult(), "[%s] Propagated.",
773                                    GetErrorMessage(GetLastResult()));
774
775                 if (pRegEntry->entryName == entryName)
776                 {
777                         entryFound = true;
778                         break;
779                 }
780         }
781
782         if (entryFound == true)
783         {
784                 return E_KEY_ALREADY_EXIST;
785         }
786
787         unique_ptr<_RegistryEntry> pRegEntry(new (std::nothrow) _RegistryEntry());
788         SysTryReturnResult(NID_IO, pRegEntry != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
789
790         unique_ptr<char[]> pEntryName(_StringConverter::CopyToCharArrayN(entryName));
791         SysTryReturnResult(NID_IO, pEntryName != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
792
793         length = strlen(pEntryName.get());
794         if (!_RegistryCore::CheckEntryName(pEntryName.get()))
795         {
796                 SysTryReturnResult(NID_IO, false, E_PARSING_FAILED, "Entry name could not be parsed.");
797         }
798
799         unique_ptr<char[]> pEntryValue(_StringConverter::CopyToCharArrayN(valStr));
800         SysTryReturnResult(NID_IO, pEntryValue != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
801
802         length = strlen(pEntryValue.get());
803         if (length > 0 && !_RegistryCore::CheckEntryValue(pEntryValue.get()))
804         {
805                 SysTryReturnResult(NID_IO, false, E_PARSING_FAILED, "Entry value could not be parsed.");
806         }
807
808         pRegEntry->entryName = entryName;
809         pRegEntry->entryValue = valStr;
810
811         r = pRegSection->__entryList.Add(*(pRegEntry.release()));
812         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagated.", GetErrorMessage(r));
813
814         _update = true;
815         return E_SUCCESS;
816 }
817
818 result
819 _RegistryCore::SetValue(const String& sectionName, const String& entryName, const String& valStr)
820 {
821         result r = E_SUCCESS;
822         bool sectionFound = false;
823         bool entryFound = false;
824         _RegistryEntry* pRegEntry = null;
825         _RegistrySection* pRegSection = null;
826         int length = 0;
827         int entryIndex = 0;
828
829         SysAssertf(_constructed == true, "Not yet constructed. Construct() should be called before use.\n");
830
831         if (_sectionList.GetCount() == 0)
832         {
833                 return E_SECTION_NOT_FOUND;
834         }
835
836         // Get section information
837         unique_ptr<IEnumerator> pEnum(_sectionList.GetEnumeratorN());
838         if (pEnum == null)
839         {
840                 return GetLastResult();
841         }
842
843         while (pEnum->MoveNext() == E_SUCCESS)
844         {
845                 pRegSection = dynamic_cast< _RegistrySection* >(pEnum->GetCurrent());
846                 SysTryReturn(NID_IO, pRegSection != null, GetLastResult(), GetLastResult(), "[%s] Propagated.",
847                                    GetErrorMessage(GetLastResult()));
848
849                 if (pRegSection->__sectionName == sectionName)
850                 {
851                         sectionFound = true;
852                         break;
853                 }
854         }
855
856         if (sectionFound == false)
857         {
858                 return E_SECTION_NOT_FOUND;
859         }
860
861         pEnum.reset(pRegSection->__entryList.GetEnumeratorN());
862         if (pEnum == null)
863         {
864                 return GetLastResult();
865         }
866
867         while (pEnum->MoveNext() == E_SUCCESS)
868         {
869                 pRegEntry = dynamic_cast< _RegistryEntry* >(pEnum->GetCurrent());
870                 SysTryReturn(NID_IO, pRegEntry != null, GetLastResult(), GetLastResult(), "[%s] Propagated.",
871                                    GetErrorMessage(GetLastResult()));
872
873                 if (pRegEntry->entryName == entryName)
874                 {
875                         entryFound = true;
876                         break;
877                 }
878                 entryIndex++;
879         }
880
881         if (entryFound == false)
882         {
883                 return E_KEY_NOT_FOUND;
884         }
885
886         if (valStr.GetLength() > 0)
887         {
888                 unique_ptr<char[]> pEntryValue(_StringConverter::CopyToCharArrayN(valStr));
889                 SysTryReturnResult(NID_IO, pEntryValue != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
890
891                 length = strlen(pEntryValue.get());
892                 if (!_RegistryCore::CheckEntryValue(pEntryValue.get()))
893                 {
894                         return E_PARSING_FAILED;
895                 }
896         }
897
898         pRegEntry->entryValue = valStr;
899         r = pRegSection->__entryList.SetAt(*pRegEntry, entryIndex);
900         SysTryReturnResult(NID_IO, !IsFailed(r), E_IO, "system error");
901
902         _update = true;
903         return E_SUCCESS;
904 }
905
906 result
907 _RegistryCore::RemoveValue(const String& sectionName, const String& entryName)
908 {
909         result r = E_SUCCESS;
910         bool sectionFound = false;
911         bool entryFound = false;
912         _RegistryEntry* pRegEntry = null;
913         _RegistrySection* pRegSection = null;
914
915         SysAssertf(_constructed == true, "Not yet constructed. Construct() should be called before use.\n");
916
917         if (_sectionList.GetCount() <= 0)
918         {
919                 return E_SECTION_NOT_FOUND;
920         }
921
922         // Get section information
923         unique_ptr<IEnumerator> pEnum(_sectionList.GetEnumeratorN());
924         if (pEnum == null)
925         {
926                 return E_SECTION_NOT_FOUND;
927         }
928
929         while (pEnum->MoveNext() == E_SUCCESS)
930         {
931                 pRegSection = dynamic_cast <_RegistrySection*>(pEnum->GetCurrent());
932                 SysTryReturn(NID_IO, pRegSection != null, GetLastResult(), GetLastResult(), "[%s] Propagated.",
933                                    GetErrorMessage(GetLastResult()));
934
935                 if (pRegSection->__sectionName == sectionName)
936                 {
937                         sectionFound = true;
938                         break;
939                 }
940         }
941
942         if (sectionFound == false)
943         {
944                 return E_SECTION_NOT_FOUND;
945         }
946
947         pEnum.reset(pRegSection->__entryList.GetEnumeratorN());
948         if (pEnum == null)
949         {
950                 return E_SECTION_NOT_FOUND;
951         }
952
953         while (pEnum->MoveNext() == E_SUCCESS)
954         {
955                 pRegEntry = dynamic_cast <_RegistryEntry*>(pEnum->GetCurrent());
956                 SysTryReturn(NID_IO, pRegEntry != null, GetLastResult(), GetLastResult(), "[%s] Propagated.",
957                                    GetErrorMessage(GetLastResult()));
958
959                 if (pRegEntry->entryName == entryName)
960                 {
961                         entryFound = true;
962                         break;
963                 }
964         }
965
966         if (entryFound == false)
967         {
968                 return E_KEY_NOT_FOUND;
969         }
970
971         r = pRegSection->__entryList.Remove(*pRegEntry, true);
972         SysTryReturnResult(NID_IO, !IsFailed(r), E_IO, "system error");
973
974         _update = true;
975         return E_SUCCESS;
976 }
977
978 result
979 _RegistryCore::Flush(void)
980 {
981         return E_SUCCESS;
982 }
983
984 result
985 _RegistryCore::Write(void)
986 {
987         SysAssertf(_constructed == true, "Not yet constructed. Construct() should be called before use.\n");
988
989         if (_pBuffer == null)
990         {
991                 SysLog(NID_IO, "The buffer is empty.");
992                 return E_SUCCESS;
993         }
994
995         result r = E_SUCCESS;
996
997         String openMode(L"w+");
998         unique_ptr<_FileImpl> pFileImpl(new (std::nothrow) _FileImpl);
999         SysTryReturnResult(NID_IO, pFileImpl != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
1000
1001         //TODO: Secure mode is to be handled
1002         r = pFileImpl->Construct(_regPath, "w+", null);
1003         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagated.", GetErrorMessage(r));
1004
1005         r = pFileImpl->Write(_pBuffer, _length);
1006         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagated.", GetErrorMessage(r));
1007
1008         r = pFileImpl->Flush();
1009         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagated.", GetErrorMessage(r));
1010
1011         return r;
1012 }
1013
1014 result
1015 _RegistryCore::PrepareToWrite(void)
1016 {
1017         SysAssertf(_constructed == true, "Not yet constructed. Construct() should be called before use.\n");
1018
1019         result r = E_SUCCESS;
1020         _RegistryEntry* pRegEntry = null;
1021         _RegistrySection* pRegSection = null;
1022         String inputBuffer;
1023
1024         delete[] _pBuffer; //clear existing buffer
1025         _pBuffer = null;
1026         _length = 0;
1027
1028         if (_write == false)
1029         {
1030                 SysLog(NID_IO, "[E_ILLEGAL_ACCESS] Registry cannot be flushed as it was opened in read only mode.");
1031                 return E_ILLEGAL_ACCESS;
1032         }
1033
1034         // if no sections, do nothing
1035         if (_sectionList.GetCount() == 0)
1036         {
1037                 unique_ptr<char[]> pFilePath(_StringConverter::CopyToCharArrayN(_regPath));
1038                 truncate(pFilePath.get(), 0);
1039
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                 result r = E_SUCCESS;
1482
1483                 if (*pSize != sizeof(double))
1484                 {
1485                         SetLastResult(E_INVALID_ARG);
1486                         return;
1487                 }
1488
1489                 r = Double::Parse(strValueEncoded, retDoubleVal);
1490                 SysTryReturnVoidResult(NID_IO, !IsFailed(r), E_PARSING_FAILED, "[%s] Propagated.", GetErrorMessage(r));
1491
1492                 *(double*) pValue = retDoubleVal;
1493                 break;
1494         }
1495
1496         case REG_VALUE_TYPE_STRING:
1497         {
1498 //              if(*pSize != sizeof(String))
1499 //              {
1500 //                      SetLastResult(E_INVALID_ARG);
1501 //                      return;
1502 //              }
1503                 *(String*) pValue = strValueEncoded;
1504                 break;
1505         }
1506
1507         case REG_VALUE_TYPE_BINARY:
1508         {
1509                 SetLastResult(E_PARSING_FAILED);
1510                 return;
1511         }
1512
1513         case REG_VALUE_TYPE_UUID:
1514         {
1515                 UuId retUuIdVal;
1516                 result r = E_SUCCESS;
1517
1518                 r = UuId::Parse(strValueEncoded, retUuIdVal);
1519                 SysTryReturnVoidResult(NID_IO, !IsFailed(r), E_PARSING_FAILED, "[%s] Propagated.", GetErrorMessage(r));
1520
1521                 *(UuId*) pValue = retUuIdVal;
1522                 break;
1523         }
1524
1525         case REG_VALUE_TYPE_UUIDSET:
1526         {
1527                 SetLastResult(E_PARSING_FAILED);
1528                 return;
1529         }
1530
1531         default:
1532                 SysAssert(0); // should not happen!
1533                 return;
1534         }
1535
1536         SetLastResult(E_SUCCESS);
1537         return;
1538 }
1539
1540 result
1541 _RegistryCore::AddSection(LinkedList& sectionList, const String& sectionName)
1542 {
1543         result r = E_SUCCESS;
1544         bool sectionFound = false;
1545
1546         // Get section information
1547         unique_ptr<IEnumerator> pEnum(sectionList.GetEnumeratorN());
1548         if (pEnum == null)
1549         {
1550                 return GetLastResult();
1551         }
1552
1553         while (pEnum->MoveNext() == E_SUCCESS)
1554         {
1555                 _RegistrySection* pRegSection = dynamic_cast <_RegistrySection*>(pEnum->GetCurrent());
1556                 SysTryReturn(NID_IO, pRegSection != null, GetLastResult(), GetLastResult(), "[%s] Propagated.",
1557                                    GetErrorMessage(GetLastResult()));
1558
1559                 if (pRegSection->__sectionName == sectionName)
1560                 {
1561                         sectionFound = true;
1562                         break;
1563                 }
1564         }
1565
1566         if (sectionFound == true)
1567         {
1568                 return E_SECTION_ALREADY_EXIST;
1569         }
1570
1571         // create a key with section name
1572         unique_ptr<_RegistrySection> pRegSection(new (std::nothrow) _RegistrySection());
1573
1574         SysTryReturnResult(NID_IO, pRegSection != null, E_OUT_OF_MEMORY,
1575                            "The memory is insufficient.");
1576
1577         pRegSection->__sectionName = sectionName;
1578
1579         // add new section and section-entry map
1580         r = sectionList.Add(*(pRegSection.release()));
1581         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagated.", GetErrorMessage(r));
1582
1583         return E_SUCCESS;
1584 }
1585
1586 result
1587 _RegistryCore::AddValue(LinkedList& sectionList, const String& sectionName, const String& entryName, const String& valStr)
1588 {
1589         result r = E_SUCCESS;
1590         bool sectionFound = false;
1591         bool entryFound = false;
1592         _RegistrySection* pRegSection = null;
1593
1594         // Get section information
1595         unique_ptr<IEnumerator> pEnum(sectionList.GetEnumeratorN());
1596         if (pEnum == null)
1597         {
1598                 return GetLastResult();
1599         }
1600
1601         while (pEnum->MoveNext() == E_SUCCESS)
1602         {
1603                 pRegSection = dynamic_cast <_RegistrySection*>(pEnum->GetCurrent());
1604                 SysTryReturn(NID_IO, pRegSection != null, GetLastResult(), GetLastResult(), "[%s] Propagated.",
1605                                    GetErrorMessage(GetLastResult()));
1606
1607                 if (pRegSection->__sectionName == sectionName)
1608                 {
1609                         sectionFound = true;
1610                         break;
1611                 }
1612         }
1613
1614         if (sectionFound == false)
1615         {
1616                 return E_SECTION_NOT_FOUND;
1617         }
1618
1619         pEnum.reset(pRegSection->__entryList.GetEnumeratorN());
1620         if (pEnum == null)
1621         {
1622                 return GetLastResult();
1623         }
1624
1625         while (pEnum->MoveNext() == E_SUCCESS)
1626         {
1627                 _RegistryEntry* pRegEntry = dynamic_cast <_RegistryEntry*>(pEnum->GetCurrent());
1628                 SysTryReturn(NID_IO, pRegEntry != null, GetLastResult(), GetLastResult(), "[%s] Propagated.",
1629                                    GetErrorMessage(GetLastResult()));
1630
1631                 if (pRegEntry->entryName == entryName)
1632                 {
1633                         entryFound = true;
1634                         break;
1635                 }
1636         }
1637
1638         if (entryFound == true)
1639         {
1640                 return E_KEY_ALREADY_EXIST;
1641         }
1642
1643         unique_ptr<_RegistryEntry> pRegEntry(new (std::nothrow) _RegistryEntry());
1644         SysTryReturnResult(NID_IO, pRegEntry != null, E_OUT_OF_MEMORY,
1645                         "The memory is insufficient.");
1646
1647         pRegEntry->entryName = entryName;
1648         pRegEntry->entryValue = valStr;
1649
1650         r = pRegSection->__entryList.Add(*(pRegEntry.release()));
1651         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagated.", GetErrorMessage(r));
1652
1653         return E_SUCCESS;
1654 }
1655
1656 bool
1657 _RegistryCore::CheckSectionName(char* pSectionName)
1658 {
1659         char* pTemp = null;
1660         int length = 0;
1661         char* pFrom = null;
1662         char* pTo = null;
1663
1664         if (pSectionName == null)
1665         {
1666                 return false;
1667         }
1668
1669         pFrom = pSectionName;
1670         length = strlen(pSectionName);
1671         pTo = pSectionName + (length - 1);
1672
1673         if (!pFrom || !pTo || pFrom > pTo)
1674         {
1675                 return false;
1676         }
1677
1678         for (pTemp = pFrom; pTemp <= pTo; pTemp++)
1679         {
1680                 if (*pTemp == '\0' || *pTemp == '\n' || *pTemp == '#' || *pTemp == '=')
1681                 {
1682                         return false;
1683                 }
1684         }
1685
1686         return true;
1687 }
1688
1689 bool
1690 _RegistryCore::CheckEntryName(char* pEntryName)
1691 {
1692         char* pTemp = null;
1693         int length = 0;
1694         char* pFrom = null;
1695         char* pTo = null;
1696
1697         if (pEntryName == null)
1698         {
1699                 return false;
1700         }
1701
1702         pFrom = pEntryName;
1703         length = strlen(pEntryName);
1704         pTo = pEntryName + (length - 1);
1705
1706         if (!pFrom || !pTo || pFrom > pTo)
1707         {
1708                 return false;
1709         }
1710
1711         for (pTemp = pFrom; pTemp <= pTo; pTemp++)
1712         {
1713                 if (*pTemp == '\0' || *pTemp == '\n' || *pTemp == '#' || *pTemp == '=')
1714                 {
1715                         return false;
1716                 }
1717         }
1718
1719         return true;
1720 }
1721
1722 bool
1723 _RegistryCore::CheckEntryValue(char* pEntryVal)
1724 {
1725         char* pTemp = null;
1726         int length = 0;
1727         char* pFrom = null;
1728         char* pTo = null;
1729
1730         if (pEntryVal == null)
1731         {
1732                 return false;
1733         }
1734
1735         pFrom = pEntryVal;
1736         length = strlen(pEntryVal);
1737         pTo = pEntryVal + (length - 1);
1738
1739         if (!pFrom || !pTo || pFrom > pTo)
1740         {
1741                 return false;
1742         }
1743
1744         for (pTemp = pFrom; pTemp <= pTo; pTemp++)
1745         {
1746                 if (*pTemp == '\0' || *pTemp == '\n')
1747                 {
1748                         return false;
1749                 }
1750         }
1751
1752         return true;
1753 }
1754
1755 result
1756 _RegistryCore::ConvertToSecureRegistry(const String& plainRegPath, const String& secureRegPath, const ByteBuffer* pKey)
1757 {
1758         result  r = E_SUCCESS;
1759
1760         if (File::IsFileExist(secureRegPath))
1761         {
1762                 r = GetLastResult();
1763                 if (r == E_SUCCESS)
1764                 {
1765                         r = E_FILE_ALREADY_EXIST;
1766                         SysLog(NID_IO, "[E_FILE_ALREADY_EXIST] The secure registry already exists.");
1767                 }
1768                 else
1769                 {
1770                         SysLog(NID_IO, "[%s]Propagated.", GetErrorMessage(r));
1771                 }
1772                 return r;
1773         }
1774
1775         unique_ptr<_NormalRegistry> pNormalReg(new (std::nothrow) _NormalRegistry());
1776         SysTryReturnResult(NID_IO, pNormalReg != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
1777
1778         r = pNormalReg->Load(plainRegPath, "r");
1779         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagated.", GetErrorMessage(r));
1780
1781         unique_ptr<_SecureRegistry> pSecureReg(new (std::nothrow) _SecureRegistry());
1782         SysTryReturnResult(NID_IO, pSecureReg != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
1783
1784         r = pSecureReg->Construct(secureRegPath, "w+", pKey);
1785         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagated.", GetErrorMessage(r));
1786
1787         if (pNormalReg->_pBuffer != null && pNormalReg->_length > 0)
1788         {
1789                 pSecureReg->_pBuffer = pNormalReg->_pBuffer;
1790                 pSecureReg->_length = pNormalReg->_length;
1791
1792                 pNormalReg->_pBuffer = null;
1793                 pNormalReg->_length = 0;
1794
1795                 r = pSecureReg->Parse();
1796                 SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagated.", GetErrorMessage(r));
1797         }
1798
1799         r = pSecureReg->Flush();
1800         SysTryReturn(NID_IO, !IsFailed(r), r, r, "[%s] Propagated.", GetErrorMessage(r));
1801
1802         return E_SUCCESS;
1803 }
1804
1805 FileLock*
1806 _RegistryCore::LockN(FileLockType lockType)
1807 {
1808         SysAssertf(_constructed == true && __pFileImpl != null, "Not yet constructed. Construct() should be called before use.\n");
1809         return __pFileImpl->LockN(lockType);
1810 }
1811
1812 FileLock*
1813 _RegistryCore::TryToLockN(FileLockType lockType)
1814 {
1815         SysAssertf(_constructed == true && __pFileImpl != null, "Not yet constructed. Construct() should be called before use.\n");
1816         return __pFileImpl->TryToLockN(lockType);
1817 }
1818
1819 }} // Tizen::Io
1820